2012-11-07 79 views
4

我有一个很大的数据框,有两个ID列,供课程和用户使用,我需要将它分成每个课程的一个数据框来做一些进一步的分析/子集。从每个单独的课程数据框中删除不少行后,我需要将它们粘在一起。将数据帧拆分为数据框列表,但如何重新合并?

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

我能做些什么来重新加入我修改过的dfs?

回答

12

这是do.call的地方。只需拨打df <- rbind(split.df)将导致一个奇怪和无用的列表对象,但do.call("rbind", split.df)应该会给你你要找的结果。

5

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

安德鲁Sannier答案工作,但拥有了rownames得到改变的副作用。 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 
1

基础R之外,还考虑:

  • data.table::rbindlist(),其结果的副作用是一个data.table
  • dplyr::bind_rows()但它的有些混乱名称将在列表中绑定行