【问题标题】:Converting a list of data frames to a single data frame and change column names将数据框列表转换为单个数据框并更改列名
【发布时间】:2016-01-06 16:28:45
【问题描述】:

下面使用dput显示我的数据。

dat <- structure(list(`60` = structure(c(25.2142857142857, 25.2142857142857, 
25.2142857142857, 16.8333333333333, 6.18181818181818, 6.45454545454545, 
39.3076923076923, 17.8, 30.2307692307692, 31.9090909090909, 338.872342659885, 
338.872342659885, 338.872342659885, 312.566239187662, 108.98770426029, 
132.000329498368, 295.499325777881, 289.05210119046, 279.319320138619, 
282.696361655751), .Dim = c(10L, 2L), .Dimnames = list(NULL, 
    c("CanCov", "Aspect"))), `100` = structure(c(22.2285714285714, 
21.8285714285714, 22.2285714285714, 17.4285714285714, 7.54054054054054, 
5.51351351351351, 32.8823529411765, 18.0285714285714, 31.3125, 
32.5833333333333, 328.300126247896, 336.611388179775, 328.300126247896, 
288.830157290819, 132.674633942446, 122.597267778504, 295.162359106757, 
254.508961455896, 280.326744650874, 287.386617538886), .Dim = c(10L, 
2L), .Dimnames = list(NULL, c("CanCov", "Aspect"))), `500` = structure(c(10.786941580756, 
10.7688787185355, 10.8489702517162, 10.7628278221209, 14.1569301260023, 
12.9438717067583, 12.8735632183908, 10.8551724137931, 20.729667812142, 
23.3722794959908, 195.270942450807, 195.540990751048, 195.662725661548, 
190.688980052674, 165.038240066186, 133.772446928244, 198.45485951978, 
188.942107644257, 203.862336021767, 217.567077176237), .Dim = c(10L, 
2L), .Dimnames = list(NULL, c("CanCov", "Aspect"))), `1000` = structure(c(10.3804067602406, 
10.3746059042706, 10.381156930126, 9.8993981083405, 13.26243567753, 
13.6912732474964, 11.3125, 9.73461208130547, 17.5430539609644, 
18.8537492844877, 174.841410186063, 174.803449739022, 174.777413321887, 
169.181037352303, 148.07213983955, 145.460198642085, 157.562633627451, 
162.484978829108, 159.688505118645, 163.433969343022), .Dim = c(10L, 
2L), .Dimnames = list(NULL, c("CanCov", "Aspect")))), .Names = c("60", 
"100", "500", "1000"))

我有一个包含四个元素(分别命名为 60、100、500 和 1000)的列表。

> str(dat)
List of 4
 $ 60  : num [1:10, 1:2] 25.21 25.21 25.21 16.83 6.18 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr [1:2] "CanCov" "Aspect"
 $ 100 : num [1:10, 1:2] 22.23 21.83 22.23 17.43 7.54 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr [1:2] "CanCov" "Aspect"
 $ 500 : num [1:10, 1:2] 10.8 10.8 10.8 10.8 14.2 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr [1:2] "CanCov" "Aspect"
 $ 1000: num [1:10, 1:2] 10.4 10.4 10.4 9.9 13.3 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr [1:2] "CanCov" "Aspect"

我想制作一个 8 x 10 的数据框,其中的列对应于列表名称。具体来说,这些列将标记为 CanCov_60、Aspect_60、CanCov_100、...、CanCov_1000、Aspect_1000,其中 CanCov_60 和 Aspect_60 的值将来自具有相应名称的列表。

我怀疑ldply 是最好用的函数,但似乎无法将这些点联系起来。

【问题讨论】:

    标签: r list dplyr


    【解决方案1】:

    您可以在 base-R 中执行此操作,方法是在您的 列表名称 上使用 lapply。首先,我们检索那个特定的数据框,然后我们更改列名并返回它。最后,我们使用do.call(cbind(...)) 来创建结果。

    编辑:我通过问题的标题并假设所有对象都是数据框并且没有检查。然而,正如@Damianofantini 指出的那样,它们实际上是矩阵。我添加了对 data.frame 的转换。

    do.call(cbind,lapply(names(dat),function(x){
      res <- dat[[x]]
      colnames(res) <- paste(colnames(res),x,sep="_")
      data.frame(res)
    }))
    

    【讨论】:

      【解决方案2】:

      可以并行化的doParallel 版本:

      library(doParallel)
      foreach(i = seq_along(dat), .combine = cbind) %do% {
        x <- dat[[i]]
        colnames(x) <- paste(colnames(x), names(dat)[i], sep = "_")
        x
      }
      

      【讨论】:

        【解决方案3】:

        这种方法与 Herka 的方法非常相似,但是,我相信它会快一点。这是因为 dplyr::bind_cols is considerably fasterdo.call(cbind()) 方法。不幸的是,要使用dplyr::bind_cols,列表中的所有元素都必须是data.frames。因此,我需要采用Map(即mapply)策略,既可以将矩阵转换为data.frame,又可以更改变量名称。

        library(dplyr)
        
        res <- Map(function(x, y){colnames(x) = paste(colnames(x), y, sep = "_"); as.data.frame(x)}, x = dat, y = names(dat)) %>%
          bind_cols(.)
        

        【讨论】:

          【解决方案4】:

          您可以遍历您的列表并将每个矩阵复制到收件人矩阵中,动态重命名列名(如您指定的那样),然后将您的收件人矩阵转换为数据框。 它不会像使用 apply 那样快,但您应该完成工作(如果您的列表很小)。

          new_dat<-matrix(nrow=10, ncol =0)
          
          for (i in 1:length(dat)){
            colnames(dat[[i]]) <- paste(colnames(dat[[i]]), "_", names(dat)[i], sep='')
            new_dat<-cbind(new_dat,dat[[i]])  
          }
          new_dat<- data.frame(new_dat, stringsAsFactors = FALSE)
          print(new_dat)
          

          【讨论】:

          • 解释你改变了什么。
          • 你是对的,这可以完成工作,但是 for 循环,尤其是在其中增长的对象并不是一个好习惯。将数据帧不必要地转换为矩阵并返回也是如此。
          • 1- Herka,你的解决方案有点优雅,谢谢。我今天学到了一些东西。 2- 列表包含矩阵,我只在最后将矩阵转换为数据框。 3-有趣的事实。要求是生成一个数据框,并且您的所有代码都返回矩阵类对象!我的代码是唯一一个返回 data.frame 的代码,但我仍然得到了一个负 1...大声笑。
          • @DamianoFantini 对不起,您对数据类型的看法是正确的。我假设它们是帖子标题所示的数据框,但没有检查/看到它们不是。已经编辑了答案并大声喊出你:)
          猜你喜欢
          • 2020-05-31
          • 1970-01-01
          • 1970-01-01
          • 2020-04-15
          • 2020-08-28
          • 2020-05-31
          • 1970-01-01
          • 2022-08-13
          • 1970-01-01
          相关资源
          最近更新 更多