我有一个很大的数据框,其中包含课程和用户的两个 ID 列,我需要将每个课程拆分为一个数据框以进行进一步的分析/子集。在从每个单独的课程数据框中删除了很多行之后,我需要将它们重新组合在一起。
你猜对了,我使用它来拆分它split
,并且它完全按照我的需要工作。然而,拆分比我想象的要难。R 文档说“unsplit
反转了 的效果” split
,但到目前为止,我在网上的阅读表明,当拆分列表的元素本身就是数据框时,情况并非如此。
我该怎么做才能重新加入我修改后的 dfs?
这是一个地方do.call
。简单地调用df <- rbind(split.df)
会导致一个奇怪且无用的列表对象,但do.call("rbind", split.df)
应该会给你你正在寻找的结果。
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 ...
在基数 R 之外,还要考虑:
data.table::rbindlist()
结果的副作用是data.table
dplyr::bind_rows()
尽管名称有些混乱,但它会跨列表绑定行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