Am'm încercarea de a inițializa o data.cadru fără rânduri. Practic, vreau să specificați tipurile de date pentru fiecare coloană și numele ei, dar nu au nici rânduri creat ca un rezultat.
Cel mai bun mi'am fost în stare să facă până acum este ceva de genul:
df <- data.frame(Date=as.Date("01/01/2000", format="%m/%d/%Y"),
File="", User="", stringsAsFactors=FALSE)
df <- df[-1,]
Care creează o data.cadru cu un singur rând care conține toate tipurile de date și nume de coloană am vrut, dar creează, de asemenea, inutil rând, care apoi trebuie să fie eliminate.
Există o modalitate mai bună de a face acest lucru?
Doar inițializa cu gol vectori:
df <- data.frame(Date=as.Date(character()),
File=character(),
User=character(),
stringsAsFactors=FALSE)
Aici's un alt exemplu cu diferite tipuri de coloane :
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
N. B. :
Inițializare a datelor.cadru cu o coloană goală de tip greșit nu împiedică completările ulterioare de rânduri având coloane de diferite tipuri. Această metodă este doar un pic sigur, în sensul că te'll corecte tipuri de coloane de la început, prin urmare, în cazul în care codul se bazează pe niște coloane de tip verificare, se va lucra chiar și cu o `date.cadru cu zero rânduri.
Dacă tu deja existente cadru de date, las's spun " df " care are coloane pe care doriți, atunci puteți crea doar un gol cadru de date prin eliminarea tuturor rânduri:
empty_df = df[FALSE,]
Observați că " df " conține încă datele, dar empty_df
nu't.
Am găsit această întrebare în căutarea pentru modul de a crea o nouă instanță cu rânduri goale, astfel încât cred că ar putea fi utile pentru unii oameni.
Ai putea folosi citit.masa cu un șir gol pentru intrare "text", după cum urmează:
colClasses = c("Date", "character", "character")
col.names = c("Date", "File", "User")
df <- read.table(text = "",
colClasses = colClasses,
col.names = col.names)
Alternativ, precizând col.nume
ca un șir de caractere:
df <- read.csv(text="Date,File,User", colClasses = colClasses)
Datorită Richard Scriven pentru îmbunătățirea
Cel mai eficient mod de a face acest lucru este de a utiliza "structura" pentru a crea o listă care are clasa "de date.cadru"
:
structure(list(Date = as.Date(character()), File = character(), User = character()),
class = "data.frame")
# [1] Date File User
# <0 rows> (or 0-length row.names)
Pentru a pune acest lucru în perspectivă, comparativ cu în prezent răspunsul acceptat, aici's-o simplă referință:
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
Doar declare
table = data.frame()
atunci când încercați să rbind
prima linie se va crea coloane
Am creat gol cadru de date folosind următorul cod
df = data.frame(id = numeric(0), jobs = numeric(0));
și a încercat să lege câteva rânduri pentru a popula la fel după cum urmează.
newrow = c(3, 4)
df <- rbind(df, newrow)
dar a început să dea incorecte nume de coloane, după cum urmează
X3 X4
1 3 4
Soluția la această este de a converti newrow de tip df, după cum urmează
newrow = data.frame(id=3, jobs=4)
df <- rbind(df, newrow)
acum oferă date corecte cadru atunci când sunt afișate cu nume de coloane, după cum urmează
id nobs
1 3 4
Dacă doriți să creați un gol de date.cadru dinamic cu nume (colnames într-o variabilă), acest lucru poate ajuta:
names <- c("v","u","w")
df <- data.frame()
for (k in names) df[[k]]<-as.numeric()
Puteți modifica tipurile fel de bine, dacă ai nevoie de atât. cum ar fi:
names <- c("u", "v")
df <- data.frame()
df[[names[1]]] <- as.numeric()
df[[names[2]]] <- as.character()
A creați un gol cadru de date, trece în numărul de rânduri și coloane necesare în următoarea funcție:
create_empty_table <- function(num_rows, num_cols) {
frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
return(frame)
}
Pentru a crea un cadru gol în timp ce specificarea clasei din fiecare coloană, trece pur și simplu un vector de dorit tipuri de date în următoarea funcție:
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)
}
Utilizați după cum urmează:
df <- create_empty_table(3, 3, c('character','logical','numeric'))
Care vă oferă:
X1 X2 X3
1 <NA> NA NA
2 <NA> NA NA
3 <NA> NA NA
Pentru a confirma opțiunile dumneavoastră, executați următoarea:
lapply(df, class)
#output
$X1
[1] "character"
$X2
[1] "logical"
$X3
[1] "numeric"
Dacă tu nu't mintea nu-specificarea tipurilor de date în mod explicit, puteți face în acest fel:
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)
Dacă doriți să declare astfel de date.cadru cu mai multe coloane, se'll fi, probabil, o durere de tip coloana clase de mână. Mai ales dacă puteți face uz de rep
, această abordare este ușor și rapid (aproximativ 15% mai rapid decât alte soluții care pot fi generalizate de genul asta):
Dacă se dorește coloana clase sunt într-un vector colClasses
, puteți face următoarele:
library(data.table)
setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)
lapply
va avea ca rezultat într-o listă de lungime dorită, fiecare element din care este pur și simplu un gol tastat vector ca numeric () " sau " număr întreg()
.
setDF
convertește această "listă", prin referire la un date.cadru`.
setnames
adaugă numele dorite de referință.
Viteza de comparație:
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
L's, de asemenea, mai rapid decât cu ajutorul "structura" într-un mod similar:
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
Dacă aveți deja un dataframe, puteți extrage metadatele (numele coloanelor și tipuri) de la un dataframe (de exemplu, dacă se controlează un BUG care este numai a declanșat cu anumite intrări și nevoie de un gol dummy Dataframe):
`` colums_and_types <- sapply(df, clasa)
print(dput(ca.personajul(nume(colums_and_types))))
dput(ca.caracter(ca.vector(colums_and_types))) ``
Și de a folosi apoi citesti.masa` pentru a crea gol dataframe
citit.masa(text = "", colClasses = c('integer', 'factor'), col.nume = c('col1', 'col2'))
Spune-ți coloana nume sunt dinamice, puteți crea un rând liber-numit matrice și transformarea acesteia într-un cadru de date.
nms <- sample(LETTERS,sample(1:10))
as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))
Această întrebare nu't a aborda în mod special preocupările mele (prezentate aici), dar în cazul în care cineva vrea să facă acest lucru cu un parametrizate numărul de coloane și fără constrângere:
> 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>
Ca divibisan membre în legătură întrebare,
...motivul [constrângere] apare [când cbinding matrici și lor constitutive tipuri] este o matrice poate avea doar un un singur tip de date. Atunci când cbind 2 matrici, rezultatul este încă o matrice și deci variabilele sunt constrâns într-un singur tip înainte conversia de date.cadru