关于r:将数据框与空数据框绑定-cbind.fill?

cbind a dataframe with an empty dataframe - cbind.fill?

我想我正在为cbind寻找rbind.fill的类似物(在Hadley的plyr包中)。 我看了看,但是没有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

我当前的解决方法是将return_df <- data.frame()行替换为return_df <- data.frame(dummy=1),然后代码起作用。 然后,我只需从return_df最后删除虚拟对象。 添加虚拟对象并运行上面的代码后,我得到

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的解决方案是直接的,也是这里最好的解决方案,但我只是使用现有的rbind.fill()提供另一种方式。

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))))                                                                                                                          
}


使用rowr::cbind.fill

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和/或矩阵进行cbind运算,而不会丢失Tyler解决方案中发生的列名

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