cbind a dataframe with an empty dataframe - cbind.fill?
我想我正在为
我想做的是以下几点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #set these just for this example one_option <- TRUE diff_option <- TRUE return_df <- data.frame() if (one_option) { #do a bunch of calculations, produce a data.frame, for simplicity the following small_df small_df <- data.frame(a=1, b=2) return_df <- cbind(return_df,small_df) } if (diff_option) { #do a bunch of calculations, produce a data.frame, for simplicity the following small2_df small2_df <- data.frame(l="hi there", m=44) return_df <- cbind(return_df,small2_df) } return_df |
可以理解,这会产生一个错误:
1 2 | Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 0, 1 |
我当前的解决方法是将
1 2 | dummy a b l m 1 1 1 2 hi there 44 |
然后我只需要摆脱虚拟对象,例如:
1 2 3 | > return_df[,2:ncol(return_df)] a b l m 1 1 2 hi there 44 |
我确定我缺少一种更简单的方法来执行此操作。
编辑:我想我不是在寻找cbind.fill,因为那将意味着将在cbind之后创建NA值,这不是我想要的。
这是一个绑定填充:
1 2 3 4 5 6 7 | cbind.fill <- function(...){ nm <- list(...) nm <- lapply(nm, as.matrix) n <- max(sapply(nm, nrow)) do.call(cbind, lapply(nm, function (x) rbind(x, matrix(, n-nrow(x), ncol(x))))) } |
让我们尝试一下:
1 2 3 4 5 6 7 | x<-matrix(1:10,5,2) y<-matrix(1:16, 4,4) z<-matrix(1:12, 2,6) cbind.fill(x,y) cbind.fill(x,y,z) cbind.fill(mtcars, mtcars[1:10,]) |
我想我是从某个地方偷来的。
从此处编辑脚本:LINK
虽然,我认为Tyler的解决方案是直接的,也是这里最好的解决方案,但我只是使用现有的
1 2 3 4 5 6 | require(plyr) # requires plyr for rbind.fill() cbind.fill <- function(...) { transpoted <- lapply(list(...),t) transpoted_dataframe <- lapply(transpoted, as.data.frame) return (data.frame(t(rbind.fill(transpoted_dataframe)))) } |
使用
1 2 3 4 5 6 7 8 | rowr::cbind.fill(df1,df2,fill = NA) A B 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 NA 6 |
qpcR软件包中的cbind.na可以做到这一点。
1 2 3 | install.packages("qpcR") library(qpcR) qpcR:::cbind.na(1, 1:7) |
我们可以添加id列,然后使用merge:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | df1 <- mtcars[1:5, 1:2] # mpg cyl id # Mazda RX4 21.0 6 1 # Mazda RX4 Wag 21.0 6 2 # Datsun 710 22.8 4 3 # Hornet 4 Drive 21.4 6 4 # Hornet Sportabout 18.7 8 5 df2 <- mtcars[6:7, 3:4] # disp hp # Valiant 225 105 # Duster 360 360 245 #Add id column then merge df1$id <- seq(nrow(df1)) df2$id <- seq(nrow(df2)) merge(df1, df2, by ="id", all.x = TRUE, check.names = FALSE) # id mpg cyl disp hp # 1 1 21.0 6 225 105 # 2 2 21.0 6 360 245 # 3 3 22.8 4 NA NA # 4 4 21.4 6 NA NA # 5 5 18.7 8 NA NA |
我只是找到了一个窍门,当我们想将列添加到一个空的数据框中时,只需在第一次绑定它,然后再绑定它。
1 2 3 4 5 6 7 8 9 10 11 | newdf <- data.frame() # add the first column newdf <- rbind(newdf,data.frame("col1"=c("row1"=1,"row2"=2))) # add the second column newdf <- cbind(newdf,data.frame("col2"=c("row1"=3,"row2"=4))) # add more columns newdf <- cbind(newdf,data.frame("col3"=c("row1"=5,"row2"=6))) # result # col1 col2 col3 #row1 1 3 5 #row2 2 4 6 |
我不知道为什么,但是对我有用。
我建议修改泰勒的答案。 我的函数允许使用向量对数据.frame和/或矩阵进行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | cbind.fill <- function(...){ nm <- list(...) dfdetect <- grepl("data.frame|matrix", unlist(lapply(nm, function(cl) paste(class(cl), collapse ="") ))) # first cbind vectors together vec <- data.frame(nm[!dfdetect]) n <- max(sapply(nm[dfdetect], nrow)) vec <- data.frame(lapply(vec, function(x) rep(x, n))) if (nrow(vec) > 0) nm <- c(nm[dfdetect], list(vec)) nm <- lapply(nm, as.data.frame) do.call(cbind, lapply(nm, function (df1) rbind(df1, as.data.frame(matrix(NA, ncol = ncol(df1), nrow = n-nrow(df1), dimnames = list(NULL, names(df1))))) )) } cbind.fill(data.frame(idx = numeric()), matrix(0, ncol = 2), data.frame(qwe = 1:3, rty = letters[1:3]), type ="GOOD", mark ="K-5") # idx V1 V2 qwe rty type mark # 1 NA 0 0 1 a GOOD K-5 # 2 NA NA NA 2 b GOOD K-5 # 3 NA NA NA 3 c GOOD K-5 |