str - esempi di ciclo for in r




Crea un data.frame vuoto (10)

È possibile utilizzare read.table con una stringa vuota per il text input come segue:

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

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

In alternativa, specificare i col.names una stringa:

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

Grazie a Richard Scriven per il miglioramento

Sto cercando di inizializzare un data.frame senza righe. Fondamentalmente, voglio specificare i tipi di dati per ogni colonna e nominarli, ma non ho nessuna riga creata come risultato.

Il meglio che sono stato in grado di fare finora è qualcosa come:

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

Che crea un data.frame con una singola riga contenente tutti i tipi di dati e i nomi di colonna che volevo, ma crea anche una riga inutile che deve quindi essere rimossa.

C'è un modo migliore per farlo?


Basta dichiarare

table = data.frame()

quando provi a rbind la prima riga creerai le colonne


Ho creato una cornice dati vuota usando il seguente codice

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

e ho cercato di associare alcune righe per popolare lo stesso come segue.

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

ma ha iniziato a dare nomi di colonne errati come segue

  X3 X4
1  3  4

La soluzione a questo è di convertire newrow a digitare df come segue

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

ora fornisce il frame di dati corretto quando viene visualizzato con i nomi delle colonne come segue

  id nobs
1  3   4 

Il modo più efficiente per farlo è usare la structure per creare una lista che abbia la classe "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)

Per mettere questo in prospettiva rispetto alla risposta attualmente accettata, ecco un semplice punto di riferimento:

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

Puoi farlo senza specificare i tipi di colonna

df = data.frame(matrix(vector(), 0, 3,
                dimnames=list(c(), c("Date", "File", "User"))),
                stringsAsFactors=F)

Questa domanda non ha affrontato in modo specifico le mie preoccupazioni ( here delineate), ma nel caso qualcuno volesse farlo con un numero parametrico di colonne e nessuna coercizione:

> require(dplyr)
> dbNames <- c('a','b','c','d')
> emptyTableOut <- 
    data.frame(
        character(), 
        matrix(integer(), ncol = 3, nrow = 0), stringsAsFactors = FALSE
    ) %>% 
    setNames(nm = c(dbNames))
> glimpse(emptyTableOut)
Observations: 0
Variables: 4
$ a <chr> 
$ b <int> 
$ c <int> 
$ d <int>

Come gli stati divisi sulla domanda collegata,

... la ragione [coercizione] si verifica [quando le matrici di cbinding e i loro tipi costitutivi] è che una matrice può avere un solo tipo di dati. Quando si cbind 2 matrici, il risultato è ancora una matrice e quindi le variabili sono tutte costrette in un unico tipo prima di convertirsi in un data.frame


Se non ti dispiace di non specificare esplicitamente i tipi di dati, puoi farlo in questo modo:

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)

Se si desidera creare un data.frame vuoto con nomi dinamici (nomi di cola in una variabile), ciò può aiutare:

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

Puoi cambiare anche i tipi se ne hai bisogno. piace:

names <- c("u", "v")
df <- data.frame()
df[[names[1]]] <- as.numeric()
df[[names[2]]] <- as.character()

Se stai cercando la mancanza:

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

quindi non è necessario specificare i nomi delle colonne separatamente. Si ottiene il tipo di colonna di default logico fino a riempire il frame di dati.


Supponi che i nomi delle tue colonne siano dinamici, puoi creare una matrice vuota con il nome di una riga e trasformarla in un frame di dati.

nms <- sample(LETTERS,sample(1:10))
as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))






r-faq