组合两个不同长度的数据帧

时间:2011-08-08 20:33:36

标签: r dataframe

我有两个数据框 第一列只有一列10行 第二个是3列50行。

当我尝试使用cbind进行组合时,会出现此错误:

  

data.frame(...,check.names = FALSE)中的错误:

有人可以建议另外一个功能吗?
P.S我也尝试使用列表,但它也会出现同样的错误。

由3列组成的数据框应该是CSV文件中的前3列,而当我使用write.table函数写入时,具有一列的数据框应该是该文件中的第4列。前3列有50行,第4列应占前10行。

9 个答案:

答案 0 :(得分:33)

plyr包中有一个函数rbind.fill,它将合并data.frames并为空单元格引入NA

library(plyr)
combined <- rbind.fill(mtcars[c("mpg", "wt")], mtcars[c("wt", "cyl")])
combined[25:40, ]

    mpg    wt cyl
25 19.2 3.845  NA
26 27.3 1.935  NA
27 26.0 2.140  NA
28 30.4 1.513  NA
29 15.8 3.170  NA
30 19.7 2.770  NA
31 15.0 3.570  NA
32 21.4 2.780  NA
33   NA 2.620   6
34   NA 2.875   6
35   NA 2.320   4

答案 1 :(得分:19)

根据后续评论,我根本不清楚OP实际上是什么。他们实际上可能正在寻找一种将数据写入文件的方法。

但是我们假设我们真正想到了cbind多个不同长度的数据帧。

cbind最终会调用data.frame,其帮助文件显示为:

  

传递给data.frame的对象应该具有相同的行数,但是   由我保护的原子矢量,因子和特征向量   必要时再循环多次(包括来自R   2.9.0,列表参数的元素)。

所以在OP的实际例子中,不应该是一个错误,因为R应该将较短的向量回收到长度为50.实际上,当我运行以下内容时:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(10),e = runif(10))
cbind(dat1,dat2)

我没有错误,更短的数据框按预期回收。但是,当我运行时:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(9), e = runif(9))
cbind(dat1,dat2)

我收到以下错误:

Error in data.frame(..., check.names = FALSE) : 
  arguments imply differing number of rows: 50, 9

但是关于R的奇妙之处在于你可以做任何你想要的事情,即使你不应该做。例如,这是一个简单的函数,cbind数据帧长度不均匀,并使用NA s自动填充较短的数据框:

cbindPad <- function(...){
args <- list(...)
n <- sapply(args,nrow)
mx <- max(n)
pad <- function(x, mx){
    if (nrow(x) < mx){
        nms <- colnames(x)
        padTemp <- matrix(NA, mx - nrow(x), ncol(x))
        colnames(padTemp) <- nms
        if (ncol(x)==0) {
          return(padTemp)
        } else {
        return(rbind(x,padTemp))
          }
    }
    else{
        return(x)
    }
}
rs <- lapply(args,pad,mx)
return(do.call(cbind,rs))
}

可以这样使用:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(10),e = runif(10))
dat3 <- data.frame(d = runif(9), e = runif(9))
cbindPad(dat1,dat2,dat3)

我不保证此功能在所有情况下都有效;它只是一个例子。

修改

如果主要目标是创建csv或文本文件,那么您需要做的就是使用""而不是NA更改要填充的功能,然后执行以下操作:

dat <- cbindPad(dat1,dat2,dat3)
rs <- as.data.frame(apply(dat,1,function(x){paste(as.character(x),collapse=",")}))

然后在write.table上使用rs

答案 2 :(得分:1)

参考Andrie的回答,建议使用plyr::rbind.fill(): 与t()结合使用时,cbind.fill()(不属于plyr)会构建您的数据框,并考虑相同的案例编号。

答案 3 :(得分:-1)

我的想法是获取所有data.frames的最大行数,然后在需要时将空矩阵附加到每个data.frame。此方法不需要额外的包,只使用base。代码如下:

list.df <- list(data.frame(a = 1:10), data.frame(a = 1:5), data.frame(a = 1:3))

max.rows <- max(unlist(lapply(list.df, nrow), use.names = F))

list.df <- lapply(list.df, function(x) {
    na.count <- max.rows - nrow(x)
    if (na.count > 0L) {
        na.dm <- matrix(NA, na.count, ncol(x))
        colnames(na.dm) <- colnames(x)
        rbind(x, na.dm)
    } else {
        x
    }
})

do.call(cbind, list.df)

#     a  a  a
# 1   1  1  1
# 2   2  2  2
# 3   3  3  3
# 4   4  4 NA
# 5   5  5 NA
# 6   6 NA NA
# 7   7 NA NA
# 8   8 NA NA
# 9   9 NA NA
# 10 10 NA NA

答案 4 :(得分:-1)

希望这对你有用!

您可以使用library(qpcR)组合两个大小不等的矩阵。

resultant_matrix <- qpcR:::cbind.na(matrix1, matrix2)

注意: - 结果矩阵的大小为matrix2。

答案 5 :(得分:-2)

我实际上并没有收到错误。

a <- as.data.frame(matrix(c(sample(letters,50, replace=T),runif(100)), nrow=50))
b <- sample(letters,10, replace=T)
c <- cbind(a,b)

我使用字母加入所有数字有不同的功能(它没有)。你的'第一个数据框',实际上只是一个矢量',在第4列中重复了5次......

但是大师对这个问题的所有评论仍然是相关的:)

答案 6 :(得分:-2)

我想我已经提出了一个相当短的解决方案。希望它可以帮到某个人。

cbind.na<-function(df1, df2){

  #Collect all unique rownames
  total.rownames<-union(x = rownames(x = df1),y = rownames(x=df2))

  #Create a new dataframe with rownames
  df<-data.frame(row.names = total.rownames)

  #Get absent rownames for both of the dataframe
  absent.names.1<-setdiff(x = rownames(df1),y = rownames(df))
  absent.names.2<-setdiff(x = rownames(df2),y = rownames(df))

  #Fill absents with NAs
  df1.fixed<-data.frame(row.names = absent.names.1,matrix(data = NA,nrow = length(absent.names.1),ncol=ncol(df1)))
  colnames(df1.fixed)<-colnames(df1)
  df1<-rbind(df1,df1.fixed)

  df2.fixed<-data.frame(row.names = absent.names.2,matrix(data = NA,nrow = length(absent.names.2),ncol=ncol(df2)))
  colnames(df2.fixed)<-colnames(df2)
  df2<-rbind(df2,df2.fixed)

  #Finally cbind into new dataframe
  df<-cbind(df,df1[rownames(df),],df2[rownames(df),])
  return(df)

}

答案 7 :(得分:-2)

只需2美分。此代码将两个矩阵或data.frames合并为一个。如果一个数据结构的行数较少,那么缺少的行将添加NA值。

combine.df <- function(x, y) {
    rows.x <- nrow(x)
    rows.y <- nrow(y)
    if (rows.x > rows.y) {
        diff <- rows.x - rows.y
        df.na <- matrix(NA, diff, ncol(y))
        colnames(df.na) <- colnames(y)
        cbind(x, rbind(y, df.na))
    } else {
        diff <- rows.y - rows.x
        df.na <- matrix(NA, diff, ncol(x))
        colnames(df.na) <- colnames(x)
        cbind(rbind(x, df.na), y)
    }
}

df1 <- data.frame(1:10, row.names = 1:10)
df2 <- data.frame(1:5, row.names = 10:14)
combine.df(df1, df2)

答案 8 :(得分:-3)

我有类似的问题,我匹配两个数据集的特定列中的条目和cbind只有匹配时。 对于两个数据集,data1&amp; data2,我在比较两者的第一列后,在data2的data1中添加一列。

for(i in 1:nrow(data1){
  for( j in 1:nrow(data2){
    if (data1[i,1]==data2[j,1]) data1[i,3]<- data2[j,2]
  }
}