2012-11-07 126 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()但它的有些混亂名稱將在列表中綁定行