【问题标题】:Split a dataframe into a list of dataframes, but how to re-merge?将数据框拆分为数据框列表,但如何重新合并?
【发布时间】:2012-11-07 19:25:23
【问题描述】:

我有一个大数据框,其中包含课程和用户的两个 ID 列,我需要将每个课程拆分为一个数据框以进行进一步的分析/子集。在从每个单独的课程数据框中删除了很多行之后,我需要将它们重新组合在一起。

我使用split 拆分它,您猜对了,这完全符合我的需要。然而,拆分比我想象的要难。 R 文档说“unsplit 颠倒了split 的效果”,但到目前为止我在网上的阅读表明,当拆分列表的元素本身就是数据框时,情况并非如此。

我该怎么做才能重新加入我修改后的 dfs?

【问题讨论】:

    标签: r split


    【解决方案1】:

    这是do.call 的地方。简单地调用 df <- rbind(split.df) 会产生一个奇怪且无用的列表对象,但 do.call("rbind", split.df) 应该会给你想要的结果。

    【讨论】:

      【解决方案2】:

      unsplit() 将在您描述的一般情况下工作/似乎工作,但不是从因此拆分的数据帧中删除行的特定情况。

      考虑

      > spl <- split(mtcars, mtcars$cyl)
      > str(spl, max = 1)
      List of 3
       $ 4:'data.frame':  11 obs. of  11 variables:
       $ 6:'data.frame':  7 obs. of  11 variables:
       $ 8:'data.frame':  14 obs. of  11 variables:
      > str(unsplit(spl, f = mtcars$cyl))
      'data.frame':   32 obs. of  11 variables:
       $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
       $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
       $ disp: num  160 160 108 258 360 ...
       $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
       $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
       $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
       $ qsec: num  16.5 17 18.6 19.4 17 ...
       $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
       $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
       $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
       $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
      

      正如我们所见,unsplit() 可以撤消拆分。但是,在对拆分数据帧进行进一步处理和更改以删除行的情况下,拆分列表中数据帧的总行数与用于拆分原始数据帧的变量之间会出现不匹配。

      如果您知道或可以计算出使用于拆分原始数据框的变量所需的更改,则可以部署 unsplit()。尽管这很可能不会是微不足道的。

      一般的解决方案是,正如@Andrew Sannier 提到的那样,do.call(rbind, ...) 成语:

      > spl <- split(mtcars, mtcars$cyl)
      > str(do.call(rbind, spl))
      'data.frame':   32 obs. of  11 variables:
       $ mpg : num  22.8 24.4 22.8 32.4 30.4 33.9 21.5 27.3 26 30.4 ...
       $ cyl : num  4 4 4 4 4 4 4 4 4 4 ...
       $ disp: num  108 146.7 140.8 78.7 75.7 ...
       $ hp  : num  93 62 95 66 52 65 97 66 91 113 ...
       $ drat: num  3.85 3.69 3.92 4.08 4.93 4.22 3.7 4.08 4.43 3.77 ...
       $ wt  : num  2.32 3.19 3.15 2.2 1.61 ...
       $ qsec: num  18.6 20 22.9 19.5 18.5 ...
       $ vs  : num  1 1 1 1 1 1 1 1 0 1 ...
       $ am  : num  1 0 0 1 1 1 0 1 1 1 ...
       $ gear: num  4 4 4 4 4 4 3 4 5 5 ...
       $ carb: num  1 2 2 1 2 1 1 1 2 2 ...
      

      【讨论】:

        【解决方案3】:

        在基数 R 之外,还要考虑:

        • data.table::rbindlist() 结果的副作用是 data.table
        • dplyr::bind_rows() 尽管名称有些混乱,但它会跨列表绑定行

        【讨论】:

          【解决方案4】:

          Andrew Sannier 的答案有效,但副作用是行名被更改。 rbind 将列表名称添加到它们,例如“Datsun 710”变成“4.Datsun 710”。可以在两者之间使用unname 来避免这个问题。

          完整示例:

          mtcars_reorder = mtcars[order(mtcars$cyl), ] #reorder based on cyl first
          l1 = split(mtcars_reorder, mtcars_reorder$cyl) #split by cyl
          l1 = unname(l1) #remove list names
          l2 = do.call(what = "rbind", l1) #unsplit
          all(l2 == mtcars_reorder) #check if matches
          #> TRUE
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-12-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-26
            相关资源
            最近更新 更多