Utwórz puste dane.ramka

Próbuję zainicjować dane.Ramka bez rzędów. Zasadniczo chcę określić typy danych dla każdej kolumny i nazwać je, ale nie mam żadnych wierszy utworzonych w wyniku.

Najlepsze co do tej pory udało mi się zrobić to coś w stylu:

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

, który tworzy dane.ramka z jednym wierszem zawierającym wszystkie typy danych i nazwy kolumn, które chciałem, ale także tworzy bezużyteczny wiersz, który następnie musi zostać usunięty.

Czy jest na to lepszy sposób?
Author: Jaap, 2012-05-21

13 answers

Po prostu zainicjalizuj go pustymi wektorami:

df <- data.frame(Date=as.Date(character()),
                 File=character(), 
                 User=character(), 
                 stringsAsFactors=FALSE) 

Oto inny przykład z różnymi typami kolumn:

df <- data.frame(Doubles=double(),
                 Ints=integer(),
                 Factors=factor(),
                 Logicals=logical(),
                 Characters=character(),
                 stringsAsFactors=FALSE)

str(df)
> str(df)
'data.frame':   0 obs. of  5 variables:
 $ Doubles   : num 
 $ Ints      : int 
 $ Factors   : Factor w/ 0 levels: 
 $ Logicals  : logi 
 $ Characters: chr 

Uwaga:

Inicjalizacja data.frame pustą kolumną niewłaściwego typu nie uniemożliwia dalszego dodawania wierszy o kolumnach różnych typów.
Ta metoda jest tylko trochę bezpieczniejsza w tym sensie, że będziesz miał prawidłowe typy kolumn od początku, stąd Jeśli Twój kod opiera się na sprawdzaniu typu kolumn, będzie praca nawet z data.frame z zerowymi rzędami.

 490
Author: digEmAll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-11 17:49:03

Jeśli masz już istniejącą ramkę danych, powiedzmy df, która ma żądane kolumny, możesz po prostu utworzyć pustą ramkę danych, usuwając wszystkie wiersze:

empty_df = df[FALSE,]

Zauważ, że df nadal zawiera dane, ale empty_df NIE.

Znalazłem to pytanie szukając sposobu tworzenia nowej instancji z pustymi wierszami, więc myślę, że może to być pomocne dla niektórych osób.

 78
Author: toto_tico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-03 01:42:53

Możesz to zrobić bez podawania typów kolumn

df = data.frame(matrix(vector(), 0, 3,
                dimnames=list(c(), c("Date", "File", "User"))),
                stringsAsFactors=F)
 70
Author: zeleniy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-10 12:03:05

Możesz użyć read.table z pustym łańcuchem wejściowym text w następujący sposób:

colClasses = c("Date", "character", "character")
col.names = c("Date", "File", "User")

df <- read.table(text = "",
                 colClasses = colClasses,
                 col.names = col.names)

Alternatywnie określając col.names jako ciąg znaków:

df <- read.csv(text="Date,File,User", colClasses = colClasses)

Podziękowania dla Richarda Scrivena za poprawę

 46
Author: Rentrop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-28 21:22:59

Najbardziej efektywnym sposobem na to jest użycie structure do utworzenia listy, która ma klasę "data.frame":

structure(list(Date = as.Date(character()), File = character(), User = character()), 
          class = "data.frame")
# [1] Date File User
# <0 rows> (or 0-length row.names)

Aby ująć to w perspektywie w porównaniu z obecnie akceptowaną odpowiedzią, Oto prosty benchmark:

s <- function() structure(list(Date = as.Date(character()), 
                               File = character(), 
                               User = character()), 
                          class = "data.frame")
d <- function() data.frame(Date = as.Date(character()),
                           File = character(), 
                           User = character(), 
                           stringsAsFactors = FALSE) 
library("microbenchmark")
microbenchmark(s(), d())
# Unit: microseconds
#  expr     min       lq     mean   median      uq      max neval
#   s()  58.503  66.5860  90.7682  82.1735 101.803  469.560   100
#   d() 370.644 382.5755 523.3397 420.1025 604.654 1565.711   100
 20
Author: Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-20 20:15:02

Jeśli szukasz krótkowzroczności:

read.csv(text="col1,col2")

Więc nie musisz określać nazw kolumn oddzielnie. Domyślny typ kolumny jest logiczny, dopóki nie wypełnisz ramki danych.

 15
Author: Marc van Oudheusden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-19 08:48:25

Utworzyłem pustą ramkę danych używając następującego kodu

df = data.frame(id = numeric(0), jobs = numeric(0));

I próbował powiązać niektóre wiersze, aby wypełnić to samo w następujący sposób.

newrow = c(3, 4)
df <- rbind(df, newrow)

Ale zaczęło podawać niepoprawne nazwy kolumn w następujący sposób

  X3 X4
1  3  4

Rozwiązaniem jest konwersja newrow do typu df w następujący sposób

newrow = data.frame(id=3, jobs=4)
df <- rbind(df, newrow)

Teraz wyświetla poprawną ramkę danych z nazwami kolumn w następujący sposób

  id nobs
1  3   4 
 9
Author: Shrikant Prabhu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-18 07:17:41

Just declare

table = data.frame()

Gdy spróbujesz rbind w pierwszej linii utworzy ona Kolumny

 8
Author: Daniel Fischer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-24 15:42:49

Jeśli chcesz utworzyć puste dane.ramka z dynamicznymi nazwami (nazwy colnames w zmiennej) może pomóc:

names <- c("v","u","w")
df <- data.frame()
for (k in names) df[[k]]<-as.numeric()

Możesz również zmienić typy, jeśli potrzebujesz. like:

names <- c("u", "v")
df <- data.frame()
df[[names[1]]] <- as.numeric()
df[[names[2]]] <- as.character()
 3
Author: Ali Khosro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-11 16:34:22

Jeśli chcesz zadeklarować taką data.frame z wieloma kolumnami, prawdopodobnie będzie trudno ręcznie wpisać wszystkie klasy kolumn. Szczególnie jeśli można skorzystać z rep, takie podejście jest łatwe i szybkie (około 15% szybciej niż inne rozwiązanie, które można uogólnić w ten sposób):

Jeśli pożądane klasy kolumn znajdują się w wektorze colClasses, możesz wykonać następujące czynności:

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

lapply spowoduje powstanie listy żądanej długości, której każdy element jest po prostu pustym wektorem jak numeric() lub integer().

setDF konwertuje to list przez odniesienie do data.frame.

setnames dodaje żądane nazwy według odniesienia.

Porównanie prędkości:

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 

Jest również szybszy niż użycie structure w podobny sposób:

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
 2
Author: MichaelChirico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-03 01:51:25

Jeśli nie masz nic przeciwko jawnemu określaniu typów danych, możesz to zrobić w ten sposób:

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)
 2
Author: Odysseus Ithaca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 17:25:37

Do Utwórz pustą ramkę danych , przekaż liczbę wierszy i kolumn potrzebnych do następującej funkcji:

create_empty_table <- function(num_rows, num_cols) {
    frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
    return(frame)
}

Aby utworzyć pustą ramkę podczas określania klasy każdej kolumny , wystarczy przekazać wektor pożądanych typów danych do następującej funkcji:

create_empty_table <- function(num_rows, num_cols, type_vec) {
  frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
  for(i in 1:ncol(frame)) {
    print(type_vec[i])
    if(type_vec[i] == 'numeric') {frame[,i] <- as.numeric(df[,i])}
    if(type_vec[i] == 'character') {frame[,i] <- as.character(df[,i])}
    if(type_vec[i] == 'logical') {frame[,i] <- as.logical(df[,i])}
    if(type_vec[i] == 'factor') {frame[,i] <- as.factor(df[,i])}
  }
  return(frame)
}

Stosować w następujący sposób:

df <- create_empty_table(3, 3, c('character','logical','numeric'))

Co daje:

   X1  X2 X3
1 <NA> NA NA
2 <NA> NA NA
3 <NA> NA NA

Aby potwierdzić swoje wybory, wykonaj następujące czynności:

lapply(df, class)

#output
$X1
[1] "character"

$X2
[1] "logical"

$X3
[1] "numeric"
 1
Author: Cybernetic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-11 19:50:51

Powiedzmy, że nazwy kolumn są dynamiczne, możesz utworzyć pustą macierz o nazwie wiersz i przekształcić ją w ramkę danych.

nms <- sample(LETTERS,sample(1:10))
as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))
 0
Author: jpmarindiaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 04:37:41