【问题标题】:combining two data frames of different lengths [closed]结合两个不同长度的数据帧[关闭]
【发布时间】:2011-08-08 20:33:36
【问题描述】:

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

当我尝试使用cbind 组合它时,它会出现以下错误:

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

谁能建议其他功能来做到这一点?
PS我也尝试过使用列表,但它给出了同样的错误。

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

【问题讨论】:

  • R 在此处正确返回错误。在您指定要对多余的行做什么之前,它不知道该怎么做。
  • 您希望不匹配的行有什么行为?
  • 正如@JD 所问,您期望什么行为?也许您正在寻找不同的行为,例如merge()。请澄清。
  • 这些是 Minitab 和 Excel 将支持的操作。 R 更有条理。
  • 如果解释一下两个data.frames之间的关系,这个问题会好很多。较小的前 10 行是否对应较大的前 10 行?还是其他一些行?听起来merge by rowname 是你想要的。

标签: r dataframe


【解决方案1】:

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

【讨论】:

  • alex 使用 cbind 而不是 rbind。
  • @Max 我的看法是,如果您尝试将两个具有不同 nrowncol 的 data.frames 组合起来,您最终会遇到同样的问题,无论您@ 987654327@ 或rbind。碰巧有一个潜在的现有解决方案使用rbind 的变体。这通常有效,不是吗?
【解决方案2】:

考虑到后续的 cmets,我根本不清楚 OP 究竟在追求什么。他们可能实际上正在寻找一种将数据写入文件的方法。

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

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

传递给 data.frame 的对象应该有相同的行数,但是 受 I 保护的原子向量、因子和字符向量将是 如有必要,可循环多次(包括从 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 长度不均匀的数据帧并自动用NAs 填充较短的帧:

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=",")}))

然后在rs 上使用write.table

【讨论】:

  • 您好,感谢您的回复,但无论如何都可以加入数据帧而不回收自身或使用 NA 值?
  • @alex - 正如我在回答中提到的,数据框是专门用于等行的特殊情况的列表。要求具有不相等行的数据框有点荒谬。你想要的是一个列表。
  • @谢谢...我的主要目的是将一堆表格发布到 csv 中,这帮助我解决了问题。
  • 当您有不同列标题的列表时?那么如何组合它们
【解决方案3】:

参考Andrie的回答,建议使用plyr::rbind.fill(): 结合t(),您将拥有类似cbind.fill()(不属于plyr)之类的内容,它将在考虑相同案例编号的情况下构建您的数据框。

【讨论】:

    【解决方案4】:

    我的想法是获取所有 data.frame 的最大行数,然后在需要时将空矩阵附加到每个 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
    

    【讨论】:

      【解决方案5】:

      希望这对你有用!

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

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

      注意:- 生成的矩阵将是 matrix2 的大小。

      【讨论】:

      • qpcR 需要一个大写的 R 才能识别包 --> resultant_matrix cran.r-project.org/web/packages/qpcR/qpcR.pdf
      【解决方案6】:

      只有我的 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)
      

      【讨论】:

        【解决方案7】:

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

        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 次...

        但是从大师到问题的所有 cmets 仍然相关:)

        【讨论】:

        • 是的,即使我得到的数据框重复次数较少(10)行,直到 50 行,但我很想知道是否有任何方法只将 10 行数据框附加到 50没有放置任何 NA 值的行..谢谢
        • 嗯,我想我现在明白你的意思了。你正在谈论制作一个csv。我想你想要 write.csv(..., na="") 这样你就不会在你的 csv 文件中打印出“NA”“NA”。是这个意思吗?
        【解决方案8】:

        我想我想出了一个更短的解决方案。希望它对某人有所帮助。

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

        【讨论】:

          【解决方案9】:

          我遇到了类似的问题,我匹配了两个数据集的特定列中的条目,并且仅在匹配时才 cbind。 对于两个数据集,data1 和 data2,在比较两者的第一列之后,我在 data1 中从 data2 添加一列。

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

          【讨论】:

            猜你喜欢
            • 2019-02-27
            • 2021-07-13
            • 1970-01-01
            • 1970-01-01
            • 2012-12-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-19
            相关资源
            最近更新 更多