Crear datos vacíos.marco
Estoy tratando de inicializar un dato.marco sin filas. Básicamente, quiero especificar los tipos de datos para cada columna y nombrarlos, pero no tener filas creadas como resultado.
Lo mejor que he podido hacer hasta ahora es algo como:
df <- data.frame(Date=as.Date("01/01/2000", format="%m/%d/%Y"),
File="", User="", stringsAsFactors=FALSE)
df <- df[-1,]
Que crea un dato.marco con una sola fila que contiene todos los tipos de datos y nombres de columna que quería, pero también crea una fila inútil que luego debe eliminarse.
¿Hay una mejor manera de hacer esto?
13 answers
Simplemente inicializarlo con vectores vacíos:
df <- data.frame(Date=as.Date(character()),
File=character(),
User=character(),
stringsAsFactors=FALSE)
Aquí hay otro ejemplo con diferentes tipos de columna:
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.:
Inicializar un data.frame
con una columna vacía del tipo incorrecto no impide nuevas adiciones de filas que tengan columnas de diferentes tipos.
Este método es un poco más seguro en el sentido de que tendrá los tipos de columna correctos desde el principio, por lo tanto, si su código se basa en alguna comprobación de tipo de columna, lo hará trabajar incluso con un data.frame
con cero filas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-11 17:49:03
Si ya tiene un marco de datos existente , digamos df
que tiene las columnas que desea, entonces puede crear un marco de datos vacío eliminando todas las filas:
empty_df = df[FALSE,]
Observe que df
todavía contiene los datos, pero empty_df
no.
Encontré esta pregunta buscando cómo crear una nueva instancia con filas vacías, así que creo que podría ser útil para algunas personas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-03 01:42:53
Puede hacerlo sin especificar los tipos de columna
df = data.frame(matrix(vector(), 0, 3,
dimnames=list(c(), c("Date", "File", "User"))),
stringsAsFactors=F)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-10 12:03:05
Puedes usar read.table
con una cadena vacía para la entrada text
de la siguiente manera:
colClasses = c("Date", "character", "character")
col.names = c("Date", "File", "User")
df <- read.table(text = "",
colClasses = colClasses,
col.names = col.names)
Alternativamente especificar el col.names
como una cadena:
df <- read.csv(text="Date,File,User", colClasses = colClasses)
Gracias a Richard Scriven por la mejora
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-28 21:22:59
La forma más eficiente de hacerlo es usar structure
para crear una lista que tenga la clase "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)
Para poner esto en perspectiva en comparación con la respuesta actualmente aceptada, aquí hay un punto de referencia simple:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-20 20:15:02
Si usted está buscando la brevedad :
read.csv(text="col1,col2")
Por lo que no es necesario especificar los nombres de las columnas por separado. Obtiene el tipo de columna predeterminado lógico hasta que rellene el marco de datos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-19 08:48:25
He creado un marco de datos vacío usando el siguiente código
df = data.frame(id = numeric(0), jobs = numeric(0));
Y trató de unir algunas filas para poblar el mismo de la siguiente manera.
newrow = c(3, 4)
df <- rbind(df, newrow)
Pero comenzó a dar nombres de columna incorrectos de la siguiente manera
X3 X4
1 3 4
La solución a esto es convertir newrow a tipo df de la siguiente manera
newrow = data.frame(id=3, jobs=4)
df <- rbind(df, newrow)
Ahora da el marco de datos correcto cuando se muestra con nombres de columna de la siguiente manera
id nobs
1 3 4
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-18 07:17:41
Sólo declarar
table = data.frame()
Cuando intente rbind
la primera línea creará las columnas
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 15:42:49
Si desea crear un dato vacío.frame con nombres dinámicos (colnames en una variable), esto puede ayudar:
names <- c("v","u","w")
df <- data.frame()
for (k in names) df[[k]]<-as.numeric()
También puede cambiar los tipos si lo necesita. como:
names <- c("u", "v")
df <- data.frame()
df[[names[1]]] <- as.numeric()
df[[names[2]]] <- as.character()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 16:34:22
Si desea declarar tal data.frame
con muchas columnas, probablemente será un dolor escribir todas las clases de columna a mano. Especialmente si puede hacer uso de rep
, este enfoque es fácil y rápido (aproximadamente un 15% más rápido que la otra solución que se puede generalizar de esta manera):
Si sus clases de columna deseadas están en un vector colClasses
, puede hacer lo siguiente:
library(data.table)
setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)
lapply
dará lugar a una lista de longitud deseada, cada elemento de los cuales es simplemente un vector de tipo vacío como numeric()
o integer()
.
setDF
convierte este list
por referencia a un data.frame
.
setnames
añade los nombres deseados por referencia.
Comparación de velocidad:
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
También es más rápido que usar structure
de una manera 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-03 01:51:25
Si no le importa no especificar explícitamente los tipos de datos, puede hacerlo de esta manera:
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-10 17:25:37
Para crear un marco de datos vacío , pase el número de filas y columnas necesarias a la siguiente función:
create_empty_table <- function(num_rows, num_cols) {
frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
return(frame)
}
Para crear un marco vacío mientras se especifica la clase de cada columna , simplemente pase un vector de los tipos de datos deseados a la siguiente función:
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)
}
Utilizar como sigue:
df <- create_empty_table(3, 3, c('character','logical','numeric'))
Que da:
X1 X2 X3
1 <NA> NA NA
2 <NA> NA NA
3 <NA> NA NA
Para confirmar sus elecciones, ejecute lo siguiente:
lapply(df, class)
#output
$X1
[1] "character"
$X2
[1] "logical"
$X3
[1] "numeric"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 19:50:51
Digamos que los nombres de las columnas son dinámicos, puede crear una matriz vacía con nombre de fila y transformarla en un marco de datos.
nms <- sample(LETTERS,sample(1:10))
as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-13 04:37:41