创build一个空的data.frame
我试图初始化data.frame没有任何行。 基本上,我想为每个列指定数据types并命名它们,但是没有创build任何行作为结果。
到目前为止,我所能做到的最好的事情是:
df <- data.frame(Date=as.Date("01/01/2000", format="%m/%d/%Y"), File="", User="", stringsAsFactors=FALSE) df <- df[-1,]
它创build了一个data.frame,其中包含了我想要的所有数据types和列名,但也创build了一个无用的行,然后需要删除。
有一个更好的方法吗?
只需用空向量初始化它:
df <- data.frame(Date=as.Date(character()), File=character(), User=character(), stringsAsFactors=FALSE)
以下是不同列types的其他示例:
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
注意:
使用错误types的空列初始化data.frame
不会阻止进一步添加具有不同types列的行。
这个方法从一开始就拥有正确的列types,因此如果你的代码依赖于一些列types检查,它甚至可以在零data.frame
工作。
您可以在不指定列types的情况下进行操作
df = data.frame(matrix(vector(), 0, 3, dimnames=list(c(), c("Date", "File", "User"))), stringsAsFactors=F)
如果你已经有了一个现存的数据框 ,比如说df
有你想要的列,那么你可以通过删除所有的行来创build一个空的数据框:
empty_df = df[FALSE,]
注意df
仍然包含数据,但是empty_df
不包含数据。
我发现这个问题寻找如何创build一个空行的新实例,所以我认为这可能对某些人有帮助。
您可以使用read.table
为空的string作为inputtext
,如下所示:
colClasses = c("Date", "character", "character") col.names = c("Date", "File", "User") df <- read.table(text = "", colClasses = colClasses, col.names = col.names)
或者将col.names
指定为一个string:
df <- read.csv(text="Date,File,User", colClasses = colClasses)
感谢Richard Scriven的改进
最有效的方法是使用structure
来创build一个包含"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)
与目前接受的答案相比,这是一个简单的基准:
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
如果你正在寻找简短:
read.csv(text="col1,col2")
所以你不需要单独指定列名。 在填充数据框之前,您将获得默认的列types逻辑。
我使用下面的代码创build了空的数据框
df = data.frame(id = numeric(0), jobs = numeric(0));
并试图绑定一些行来填充相同的如下。
newrow = c(3, 4) df <- rbind(df, newrow)
但它开始提供不正确的列名如下
X3 X4 1 3 4
解决这个问题的方法是将newrow转换为dftypes,如下所示
newrow = data.frame(id=3, jobs=4) df <- rbind(df, newrow)
现在在显示列名时给出正确的数据框,如下所示
id nobs 1 3 4
只要声明table = data.frame()当你尝试rbind的第一行就会创build列
如果你想要声明这样一个有很多列的data.frame
,那么用手input所有的列类可能会很data.frame
。 特别是如果你可以使用rep
,这种方法简单快捷(比其他解决scheme的速度快15%左右):
如果您所需的列类位于向量colClasses
,则可以执行以下操作:
library(data.table) setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)
lapply
会生成一个所需长度的列表,其中的每个元素只是一个空的types向量,如numeric()
或integer()
。
setDF
通过引用setDF
转换这个list
。
setnames
通过引用添加所需的名称。
速度比较:
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
它也比以类似的方式使用structure
更快:
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
如果你不介意不明确指定数据types,你可以这样做:
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)
如果你想创build一个空的data.frame与dynamic名称(colnames在一个variables),这可以帮助:
names <- c("v","u","w") df <- data.frame() for (k in names) df[[k]]<-as.numeric()
如果你需要,你也可以改变types。 喜欢:
names <- c("u", "v") df <- data.frame() df[[names[1]]] <- as.numeric() df[[names[2]]] <- as.character()
要创build一个空的数据框 ,请将所需的行数和列数传递给以下函数:
create_empty_table <- function(num_rows, num_cols) { frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols)) return(frame) }
要在指定每列的类时创build一个空框架,只需将所需数据types的vector传递到以下函数中:
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) }
使用方法如下:
df <- create_empty_table(3, 3, c('character','logical','numeric'))
这使:
X1 X2 X3 1 <NA> NA NA 2 <NA> NA NA 3 <NA> NA NA
要确认您的select,请运行以下命令:
lapply(df, class) #output $X1 [1] "character" $X2 [1] "logical" $X3 [1] "numeric"
假设你的列名是dynamic的,你可以创build一个空的行名matrix,并将其转换为数据框。
nms <- sample(LETTERS,sample(1:10)) as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))