604 Stimmen

Erstellen Sie einen leeren data.frame

Ich versuche, einen data.frame ohne Zeilen zu initialisieren. Im Grunde möchte ich die Datentypen für jede Spalte angeben und sie benennen, aber keine Zeilen als Ergebnis erstellen lassen.

Das Beste, was ich bisher machen konnte, ist so etwas wie:

df <- data.frame(Date=as.Date("01/01/2000", format="%m/%d/%Y"), 
                 File="", User="", stringsAsFactors=FALSE)
df <- df[-1,]

Dadurch wird ein data.frame mit einer einzigen Zeile erstellt, die alle gewünschten Datentypen und Spaltennamen enthält, aber es wird auch eine nutzlose Zeile erstellt, die dann entfernt werden muss.

Gibt es eine bessere Möglichkeit, dies zu tun?

7voto

Rushabh Patel Punkte 2612

Mit Hilfe von data.table können wir Datentypen für jede Spalte angeben.

library(data.table)    
data=data.table(a=numeric(), b=numeric(), c=numeric())

6voto

Wenn es Ihnen nichts ausmacht, die Datentypen nicht explizit anzugeben, können Sie dies auf diese Weise tun:

headers<-c("Date","File","User")
df <- as.data.frame(matrix(,ncol=3,nrow=0))
names(df)<-headers

#then bind incoming data frame with col types to set data types
df<-rbind(df, new_df)

3voto

MichaelChirico Punkte 32476

Wenn Sie eine solche Erklärung abgeben wollen data.frame Bei vielen Spalten wird es wahrscheinlich mühsam sein, alle Spaltenklassen von Hand einzutippen. Vor allem, wenn Sie die folgenden Funktionen nutzen können rep Dieser Ansatz ist einfach und schnell (etwa 15 % schneller als die andere Lösung, die auf diese Weise verallgemeinert werden kann):

Wenn die gewünschten Spaltenklassen in einem Vektor enthalten sind colClasses können Sie wie folgt vorgehen:

library(data.table)
setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)

lapply ergibt eine Liste der gewünschten Länge, wobei jedes Element einfach ein leerer typisierter Vektor ist wie numeric() o integer() .

setDF wandelt diese list durch Bezugnahme auf eine data.frame .

setnames fügt die gewünschten Namen per Verweis hinzu.

Vergleich der Geschwindigkeit:

classes <- c("character", "numeric", "factor",
             "integer", "logical","raw", "complex")

NN <- 300
colClasses <- sample(classes, NN, replace = TRUE)
col.names <- paste0("V", 1:NN)

setDF(lapply(colClasses, function(x) eval(call(x))))

library(microbenchmark)
microbenchmark(times = 1000,
               read = read.table(text = "", colClasses = colClasses,
                                 col.names = col.names),
               DT = setnames(setDF(lapply(colClasses, function(x)
                 eval(call(x)))), col.names))
# Unit: milliseconds
#  expr      min       lq     mean   median       uq      max neval cld
#  read 2.598226 2.707445 3.247340 2.747835 2.800134 22.46545  1000   b
#    DT 2.257448 2.357754 2.895453 2.401408 2.453778 17.20883  1000  a 

Es ist auch schneller als die Verwendung von structure in ähnlicher Weise:

microbenchmark(times = 1000,
               DT = setnames(setDF(lapply(colClasses, function(x)
                 eval(call(x)))), col.names),
               struct = eval(parse(text=paste0(
                 "structure(list(", 
                 paste(paste0(col.names, "=", 
                              colClasses, "()"), collapse = ","),
                 "), class = \"data.frame\")"))))
#Unit: milliseconds
#   expr      min       lq     mean   median       uq       max neval cld
#     DT 2.068121 2.167180 2.821868 2.211214 2.268569 143.70901  1000  a 
# struct 2.613944 2.723053 3.177748 2.767746 2.831422  21.44862  1000   b

3voto

toto_tico Punkte 15863

Wenn Sie bereits einen Datenrahmen haben, können Sie Extrahieren der Metadaten (Spaltennamen und -typen) aus einem Datenrahmen (z. B. wenn Sie kontrollieren ein BUG die nur bei bestimmten Eingaben ausgelöst wird und einen leeren Dummy-Dataframe benötigt):

colums_and_types <- sapply(df, class)

# prints: "c('col1', 'col2')"
print(dput(as.character(names(colums_and_types))))

# prints: "c('integer', 'factor')"
dput(as.character(as.vector(colums_and_types)))

Und verwenden Sie dann die read.table um den leeren Datenrahmen zu erstellen

read.table(text = "",
   colClasses = c('integer', 'factor'),
   col.names = c('col1', 'col2'))

2voto

stevec Punkte 25346

Ich habe diese Funktion immer griffbereit, wenn ich sie benötige, und ändere die Spaltennamen und Klassen entsprechend dem Anwendungsfall:

make_df <- function() { data.frame(name=character(),
                     profile=character(),
                     sector=character(),
                     type=character(),
                     year_range=character(),
                     link=character(),
                     stringsAsFactors = F)
}

make_df()
[1] name       profile    sector     type       year_range link      
<0 rows> (or 0-length row.names)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X