Wie kann eine Zeile zu einem Datenrahmen in R hinzugefügt werden?

129

Wie fügt man in R einem Datenrahmen eine neue Zeile hinzu, nachdem der Datenrahmen bereits initialisiert wurde?

Bisher habe ich Folgendes:

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

Jede Hilfe wäre dankbar

Rilcon42
quelle
1
Weisen Sie auch Namen dezu. names(de) <- c("hello","goodbye")undrbind
Khashaa
3
Oder in einer Zeilerbind(df, setNames(de, names(df)))
Rich Scriven
2
Dies ist wirklich ein Bereich, in dem die Basis R kläglich versagt und der schon lange besteht: stackoverflow.com/questions/13599197/…
E-Mail
1
@thelatemail nicht einverstanden. Datenrahmen sind eine spezielle Struktur in r. Eine Liste von Listen mit allgemeinen Dimnamen sowie Attributen und Methoden. Ich denke es wird sehr erwartet, dass man nicht kann rbind(data.frame(a = 1), data.frame(b = 2)).. warum willst du das? Ich würde hoffen, dass das trotzdem einen Fehler auslösen würde. Es ist wie mergemit einer Zufallsvariablen by. Und das ist 2015, nicht alle options(stringsAsFactors = FALSE)?
rawr
1
@rawr - sicher, verschiedene Namen sollten nicht gebunden werden, aber R kann nicht damit umgehen, keine Namen an keine Namen zu binden, Namen an keine Namen mit denselben Dimensionen zu binden oder neue Daten zu binden, um neue Faktorstufen aufzunehmen. Ich denke das ist eine Schwäche. Insbesondere, wenn es darum geht, wiederholte Namen und alle NA-Namen zu binden. Und das Einstellen stringsAsFactors=FALSEkann eine schnelle Lösung sein, aber das Ändern der Standardeinstellungen, die andere Leute anders eingestellt haben, kann einen Tag wirklich ruinieren.
E-Mail

Antworten:

131

Wie @Khashaa und @Richard Scriven in Kommentaren hervorheben, müssen Sie für alle Datenrahmen, die Sie anhängen möchten, konsistente Spaltennamen festlegen.

Daher müssen Sie die Spaltennamen für den zweiten Datenrahmen explizit deklarieren deund dann verwenden rbind(). Sie legen nur Spaltennamen für den ersten Datenrahmen fest 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
quelle
Vielen Dank! Haben Sie eine Idee, wie Sie dies beheben können, wenn ich keinen zweiten Datenrahmen deklariert habe, sondern jeden Wert, den ich einer neuen Zeile hinzufügen möchte, als Variable gespeichert habe?
Rilcon42
8
Versuchen Sie: newdf<-rbind(df, data.frame(hello="hola", goodbye="ciao"))ODER mit Variable:newdf<-rbind(df, data.frame(hello=var1, goodbye=var2))
Parfait
108

Machen wir es einfach:

df[nrow(df) + 1,] = c("v1","v2")
Matheus Araujo
quelle
9
Dies führt zu Problemen beim Versuch, eine neue Zeile mit gemischten Datentypen (einige Zeichenfolgen, einige numerische) hinzuzufügen. In einem solchen Fall werden sogar die numerischen Werte in Zeichenfolgen konvertiert. Eine Problemumgehung besteht darin, die Werte separat hinzuzufügen, etwa wie folgt (vorausgesetzt, es gibt 3 Spalten): df[nrow(df) + 1, 1:2] = c("v1", "v2")und df[nrow(df), 3] = 100dennoch ist es ein guter Punkt, eine neue Zeile hinzuzufügen. Also, +1
The Student Soul
17
Oder verwenden Sie "Liste" anstelle von "c".
Ytsen de Boer
nette Idee, aber wie kann ich tun, wenn ich eine neue Zeile an der ersten Position einfügen oder hinzufügen möchte?
Darwin PC
1
Versuchte dies mit data.table, sagt aber mit nrow + 1 ist außerhalb des Bereichs.
Herman Toothrot
1
@Arani gibt es schon eine Antwort mit list(). Ich habe Ihre Bearbeitung zurückgesetzt.
M--
41

Oder, inspiriert von @MatheusAraujo:

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

Dies würde gemischte Datentypen ermöglichen.

Ytsen de Boer
quelle
24

Es gibt jetzt add_row()aus den tibbleoder tidyversePaketen.

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

Nicht spezifizierte Spalten erhalten eine NA.

Joe
quelle
Ich mochte diesen Ansatz, wenn Sie sich an die Tidyverse-Philosophie halten. Andernfalls ist die grundlegende R-Syntax eine Überlebensfähigkeit, die sich in einer Umgebung als nützlich erweist, in der Sie keine Berechtigungen zum Importieren von Paketen haben. Mir gefällt besonders die Antwort mit einfacher R-Syntax mit rbindund as.matrix darunter
Pablo Adames
17

Ich mag liststatt, cweil es gemischte Datentypen besser handhabt. Hinzufügen einer zusätzlichen Spalte zur Frage des Originalplakats:

#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)

Beachten Sie, dass eine zusätzliche Steuerung erforderlich ist, wenn die Zeichenfolge / Faktor-Konvertierung wichtig ist.

Oder verwenden Sie die ursprünglichen Variablen mit der Lösung von MatheusAraujo / Ytsen de Boer:

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

Beachten Sie, dass diese Lösung mit den Zeichenfolgen nur dann gut funktioniert, wenn Daten im Datenrahmen vorhanden sind.

gsk9
quelle
Wenn hellound goodbyeim Zeichen in sind df, können Sie Folgendes tun. Sie verwenden nicht unbedingt Namen in einer Liste. df <- data.frame(hello = "hi", goodbye = "bye", volume = 1,stringsAsFactors = FALSE); rbind(df, list("hola", "ciao", 100)).
Jazzurro
11

Nicht besonders elegant, aber:

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

Aus der Dokumentation der rbindFunktion:

Denn rbindSpaltennamen werden aus dem ersten Argument mit entsprechenden Namen übernommen: Spaltennamen für eine Matrix ...

J. Win.
quelle
Diese Lösung funktioniert, ohne dass die hinzuzufügenden Spalten angegeben werden müssen, was für Anwendungen mit großen
Datenmengen
1

Ich muss stringsAsFactors=FALSEbeim Erstellen des Datenrahmens hinzufügen.

> 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
quelle
1

stringsAsFactors=FALSEStellen Sie sicher, dass Sie beim Erstellen des Datenrahmens Folgendes angeben:

> 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"

Wenn Sie stringsAsFactors=FALSEden Datenrahmen nicht erstellen, wird beim Versuch, die neue Zeile hinzuzufügen, der folgende Fehler angezeigt:

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

Es gibt eine einfachere Möglichkeit, einen Datensatz von einem Datenrahmen an einen anderen anzuhängen, wenn Sie wissen, dass die beiden Datenrahmen dieselben Spalten und Typen verwenden. Anhängen eine Zeile aus xxzu yynur folgendes tun , wo idie i‚ten Zeile in xx.

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

So einfach ist das. Keine unordentlichen Bindungen. Wenn Sie alle anhängen müssen xxan yy, dann rufen Sie entweder eine Schleife oder nutzen Sequenz Fähigkeiten des R und dies tun:

zz[(nrow(zz)+1):(nrow(zz)+nrow(yy)),] <- yy[1:nrow(yy),]
Patrick Champion
quelle
0

Wenn Sie einen leeren Datenrahmen erstellen und Inhalte in einer Schleife hinzufügen möchten, kann Folgendes hilfreich sein:

# 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

Ich hoffe es hilft :)

Edwin Pratt
quelle