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

Rilcon42
źródło
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)
Parfait
źródło
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")
Matheus Araujo
źródło
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.

Ytsen de Boer
źródło
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.

Joe
źródło
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.

gsk9
źródło
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 ...

J. Win.
źródło
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
> 
nealei
źródło
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
OracleJavaNet
źródło
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),]
Patrick Champion
źródło
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 :)

Edwin Pratt
źródło