W jaki sposób można dodać wiersz do ramki danych w języku R?


129

W R, jak dodać nowy wiersz do ramki danych, gdy ramka danych została już zainicjowana?

Jak dotąd mam to:

df <- data.frame("hi", "bye")
names(df) <- c("hello", "goodbye")

#I am trying to add "hola" and "ciao" as a new row
de <- data.frame("hola", "ciao")

merge(df, de) # Adds to the same row as new columns

# Unfortunately, I couldn't find an rbind() solution that wouldn't give me an error

Każda pomoc będzie mile widziana


1
przypisać też imiona de. names(de) <- c("hello","goodbye")irbind
— Khashaa,

3
Lub w jednej linijcerbind(df, setNames(de, names(df)))
— Rich Scriven

2
To naprawdę jest obszar, w którym podstawowe R zawodzi żałośnie i ma przez długi czas: stackoverflow.com/questions/13599197/ ...
— thelatemail

1
@thelatemail nie zgadzam się. ramki danych są specjalną strukturą w r. lista list ze wspólnymi nazwami wymiarów i atrybutami oraz metodami. Myślę, że jest bardzo oczekiwane, że nie można rbind(data.frame(a = 1), data.frame(b = 2))… dlaczego miałbyś chcieć? Mam nadzieję, że mimo wszystko spowoduje to błąd. To jak mergez losową byzmienną. A to jest rok 2015, czy nie wszyscy ustawiają options(stringsAsFactors = FALSE)?
— rawr

1
@rawr - oczywiście, różne nazwy nie powinny być wiązane, ale R nie radzi sobie z wiązaniem żadnych nazw z żadnymi nazwami, wiązaniem nazw z żadnymi nazwami o tych samych wymiarach ani wiązaniem nowych danych w celu włączenia nowych poziomów czynników. Myślę, że to słabość. Szczególnie, gdy może obsługiwać wiązanie powtarzających się nazw i wszystkich nazw NA. Ustawienie stringsAsFactors=FALSEmoże być szybką naprawą, ale zmiana ustawień domyślnych, które inni ludzie ustawią inaczej, może naprawdę zrujnować dzień.
— thelatemail

Odpowiedzi:


131

Podobnie jak @Khashaa i @Richard Scriven wskazują w komentarzach, musisz ustawić spójne nazwy kolumn dla wszystkich ramek danych, które chcesz dołączyć.

Dlatego musisz jawnie zadeklarować nazwy kolumn dla drugiej ramki danych de, a następnie użyć rbind(). Ustawiasz tylko nazwy kolumn dla pierwszej ramki danych df:

df<-data.frame("hi","bye")
names(df)<-c("hello","goodbye")

de<-data.frame("hola","ciao")
names(de)<-c("hello","goodbye")

newdf <- rbind(df, de)

Dzięki! Każdy pomysł, jak to naprawić, jeśli nie mam zadeklarowanej drugiej ramki danych, ale zamiast tego mam każdą wartość, którą chcę dodać do nowego wiersza, przechowywaną jako zmienna?
— Rilcon42,

8
Spróbuj: newdf<-rbind(df, data.frame(hello="hola", goodbye="ciao"))LUB ze zmienną:newdf<-rbind(df, data.frame(hello=var1, goodbye=var2))
— Parfait

109

Uprośćmy to:

df[nrow(df) + 1,] = c("v1","v2")

10
Powoduje to problemy podczas próby dodania nowego wiersza z mieszanymi typami danych (niektóre ciągi, niektóre liczby). W takim przypadku nawet wartości liczbowe są konwertowane na łańcuch. Jednym obejściem jest dodanie wartości osobno, coś podobnego do następującego (zakładając, że są 3 kolumny): df[nrow(df) + 1, 1:2] = c("v1", "v2")i df[nrow(df), 3] = 100Ale nadal warto dodać nowy wiersz. Tak więc, +1
— The Student Soul,

17
Lub użyj „list” zamiast „c”.
— Ytsen de Boer

fajny pomysł, ale jak mam to zrobić, jeśli chcę wstawić lub dodać nowy wiersz na pierwszej pozycji?
— Darwin PC

1
Wypróbowałem to z data.table, ale mówi z nrow + 1 jest poza zakresem.
— Herman Toothrot

1
@Arani jest już odpowiedź z list(). Cofnąłem twoją edycję.
— M--

41

Lub, zgodnie z inspiracją @MatheusAraujo:

df[nrow(df) + 1,] = list("v1","v2")

Pozwoliłoby to na mieszane typy danych.


24

Jest teraz add_row()z pakietów tibblelub tidyverse.

library(tidyverse)
df %>% add_row(hello = "hola", goodbye = "ciao")

Nieokreślone kolumny otrzymują plik NA.


Podobało mi się to podejście, jeśli trzymasz się filozofii uporządkowanej wersji. W przeciwnym razie podstawowa składnia języka R to umiejętność przetrwania, która przydaje się, gdy jesteś w środowisku, w którym nie masz uprawnień do importowania pakietów. Szczególnie podoba mi się odpowiedź przy użyciu zwykłej składni R z rbindi as.matrix poniżej
— Pablo Adames

17

Lubię listzamiast, cponieważ lepiej obsługuje mieszane typy danych. Dodanie dodatkowej kolumny do pytania pierwotnego autora:

#Create an empty data frame
df <- data.frame(hello=character(), goodbye=character(), volume=double())
de <- list(hello="hi", goodbye="bye", volume=3.0)
df = rbind(df,de, stringsAsFactors=FALSE)
de <- list(hello="hola", goodbye="ciao", volume=13.1)
df = rbind(df,de, stringsAsFactors=FALSE)

Należy pamiętać, że wymagana jest dodatkowa kontrola, jeśli konwersja ciągów / współczynników jest ważna.

Lub używając oryginalnych zmiennych z rozwiązaniem MatheusAraujo / Ytsen de Boer:

df[nrow(df) + 1,] = list(hello="hallo",goodbye="auf wiedersehen", volume=20.2)

Zauważ, że to rozwiązanie nie działa dobrze w przypadku ciągów, chyba że istnieją dane w ramce danych.


Jeśli helloi goodbyemasz charakter df, możesz wykonać następujące czynności. Nie musisz koniecznie używać nazw na liście. df <- data.frame(hello = "hi", goodbye = "bye", volume = 1,stringsAsFactors = FALSE); rbind(df, list("hola", "ciao", 100)).
— jazzurro

11

Niezbyt eleganckie, ale:

data.frame(rbind(as.matrix(df), as.matrix(de)))

Z dokumentacji rbindfunkcji:

Dla rbindnazw kolumn pobierane są z pierwszego argumentu o odpowiednich nazwach: nazwy kolumn dla macierzy ...


To rozwiązanie działa bez konieczności określania kolumn do dodania, co jest znacznie lepsze w przypadku aplikacji na dużych
— zbiorach

1

Muszę dodać stringsAsFactors=FALSEpodczas tworzenia ramki danych.

> df <- data.frame("hello"= character(0), "goodbye"=character(0))
> df
[1] hello   goodbye
<0 rows> (or 0-length row.names)
> df[nrow(df) + 1,] = list("hi","bye")
Warning messages:
1: In `[<-.factor`(`*tmp*`, iseq, value = "hi") :
  invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, iseq, value = "bye") :
  invalid factor level, NA generated
> df
  hello goodbye
1  <NA>    <NA>
> 

.

> df <- data.frame("hello"= character(0), "goodbye"=character(0), stringsAsFactors=FALSE)
> df
[1] hello   goodbye
<0 rows> (or 0-length row.names)
> df[nrow(df) + 1,] = list("hi","bye")
> df[nrow(df) + 1,] = list("hola","ciao")
> df[nrow(df) + 1,] = list(hello="hallo",goodbye="auf wiedersehen")
> df
  hello         goodbye
1    hi             bye
2  hola            ciao
3 hallo auf wiedersehen
> 

1

Upewnij się, aby określić stringsAsFactors=FALSEpodczas tworzenia dataframe:

> rm(list=ls())
> trigonometry <- data.frame(character(0), numeric(0), stringsAsFactors=FALSE)
> colnames(trigonometry) <- c("theta", "sin.theta")
> trigonometry
[1] theta     sin.theta
<0 rows> (or 0-length row.names)
> trigonometry[nrow(trigonometry) + 1, ] <- c("0", sin(0))
> trigonometry[nrow(trigonometry) + 1, ] <- c("pi/2", sin(pi/2))
> trigonometry
  theta sin.theta
1     0         0
2  pi/2         1
> typeof(trigonometry)
[1] "list"
> class(trigonometry)
[1] "data.frame"

stringsAsFactors=FALSENiepowodzenie użycia podczas tworzenia ramki danych spowoduje następujący błąd podczas próby dodania nowego wiersza:

> trigonometry[nrow(trigonometry) + 1, ] <- c("0", sin(0))
Warning message:
In `[<-.factor`(`*tmp*`, iseq, value = "0") :
  invalid factor level, NA generated

0

Istnieje prostszy sposób na dołączenie rekordu z jednej ramki danych do drugiej, JEŚLI wiesz, że te dwie ramki danych mają te same kolumny i typy. Aby dołączyć jeden wiersz od xxdo, yypo prostu wykonaj następujące czynności, gdzie ijest iósmy wiersz xx.

yy[nrow(yy)+1,] <- xx[i,]

Proste. Bez bałaganu. Jeśli chcesz dołączyć wszystko xxdo yy, wywołaj pętlę lub skorzystaj z możliwości sekwencji R i zrób to:

zz[(nrow(zz)+1):(nrow(zz)+nrow(yy)),] <- yy[1:nrow(yy),]

0

Jeśli chcesz utworzyć pustą ramkę danych i dodać zawartość w pętli, pomocne mogą być następujące czynności:

# Number of students in class
student.count <- 36

# Gather data about the students
student.age <- sample(14:17, size = student.count, replace = TRUE)
student.gender <- sample(c('male', 'female'), size = student.count, replace = TRUE)
student.marks <- sample(46:97, size = student.count, replace = TRUE)

# Create empty data frame
student.data <- data.frame()

# Populate the data frame using a for loop
for (i in 1 : student.count) {
    # Get the row data
    age <- student.age[i]
    gender <- student.gender[i]
    marks <- student.marks[i]

    # Populate the row
    new.row <- data.frame(age = age, gender = gender, marks = marks)

    # Add the row
    student.data <- rbind(student.data, new.row)
}

# Print the data frame
student.data

Mam nadzieję, że to pomoże :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.