为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

千巷猫影 2019-11-18 14:23:49
我有两个数据框。第一个只有一列十行。第二个是3列50行。当我尝试通过使用进行组合时cbind,出现以下错误:data.frame(...,check.names = FALSE)错误:谁能建议另一个功能来做到这一点?PS我也尝试过使用列表,但这给出了同样的错误。当我使用该write.table函数编写代码时,由3列组成的数据框应为CSV文件中的前3列,而具有一列的数据框应为该文件中的第四列。前三列有50行,第四列应占前10行。
查看完整描述

3 回答

?
MM们

TA贡献1886条经验 获得超2个赞

在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


查看完整回答
反对 回复 2019-11-18
?
莫回无

TA贡献1865条经验 获得超7个赞

鉴于后续评论,我尚不清楚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对长度不均匀的数据帧进行数据处理,并使用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或文本文件,那么您要做的所有事情都会将功能更改为pad ""而不是NA,然后执行以下操作:


dat <- cbindPad(dat1,dat2,dat3)

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

然后write.table在上使用rs。


查看完整回答
反对 回复 2019-11-18
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

我的想法是获取所有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


查看完整回答
反对 回复 2019-11-18
  • 3 回答
  • 0 关注
  • 745 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信