首页 文章

合并两个不同长度的数据帧[关闭]

提问于
浏览
29

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

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

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

任何人都可以建议另一个功能吗?
P.S我也尝试使用列表,但它也给出了相同的错误 .

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

9 回答

  • -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
    
  • -2

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

    但是让's assume that we'真的在一种不同长度的多个数据帧的方式之后 .

    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 数据帧长度不均匀并自动填充较短的 NA

    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)
    

    我不保证这个功能适用于所有情况;它只是一个例子 .

    EDIT

    如果主要目标是创建一个csv或文本文件,那么你需要做的就是使用 "" 而不是 NA 来改变要填充的函数,然后执行以下操作:

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

    然后在 rs 上使用 write.table .

  • 19

    参考Andrie的回答,建议使用 plyr::rbind.fill() :结合 t() ,你有 cbind.fill() (不是 plyr 的一部分),它将构建你的数据框,同时考虑相同的案例编号 .

  • 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
    
  • -2

    希望这对你有用!

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

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

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

  • -1

    我实际上并没有得到这个错误 .

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

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

  • -3

    我想我已经提出了一个相当短的解决方案..希望它有助于某人 .

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

    我有类似的问题,我匹配两个数据集的特定列中的条目和cbind只有匹配 . 对于两个数据集data1和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]
      }
    }
    

相关问题