我需要帮助思考如何拆分数据框以执行操作

I need help thinking about how to split a data frame to perform operations

我是 R 的新手,很难思考解决问题的正确方法。我习惯于在 excel 中进行大部分数据分析,所以我认为我陷入了电子表格领域。现在我要处理的数据太大,无法在 excel 中轻松处理,所以我想深入了解并使用 R。在此先感谢您提供的任何帮助。

所以让我们以 ChickWeight 为例:

> head(ChickWeight)
  weight Time Chick Diet
1     42    0     1    1
2     51    2     1    1
3     59    4     1    1
4     64    6     1    1
5     76    8     1    1
6     93   10     1    1

假设我希望能够按饮食和时间点拆分数据框,这样可以很容易地生成 table 的平均权重,其中 Time 用于列,Diet 用于行。类似于:

  0   2   4   6 (time)
1   
2    <average weights
3         go in here>
4
(diet)

在我看来,最简单的方法是生成一个包含这些值的二维数组,以便我可以像 average_weight[<Time>][<Diet>].

一样访问它们

我也想使用 average_weight[<Time>][]

之类的方法轻松获取给定时间或给定饮食的所有平均体重

我觉得我没有正确考虑这个问题,因为我发现的 none 工具似乎为我指明了正确的方向。我得到的最接近的是使用 split()

chicks_by_time_and_diet <- split(ChickWeight, list(ChickWeight$Time, ChickWeight$Diet))

但是这个returns一个长度为55的列表,不是二维数组。我也尝试调查 plyr。这听起来正是我想要的,但我不清楚如何为此使用它。

感谢任何帮助,谢谢!

奖金: 实际上,我的数据框比 ChickWeight 有更多的因素,如果可以访问给定 'Time' 和 'Diet' 的所有因素,那将是理想的。

例如假设 ChickWeight 有另一个因素 height。是否可以将给定饮食的平均值 heightweight 存储在数组中的特定位置,以便 average_weight_and_height[<Time>][<Diet>] returns (weight, height)?

tapply 就是为此而生的:

> with(ChickWeight, tapply(weight, list(Time, Diet), mean))
           1     2     3        4
0   41.40000  40.7  40.8  41.0000
2   47.25000  49.4  50.4  51.8000
4   56.47368  59.8  62.2  64.5000
6   66.78947  75.4  77.9  83.9000
8   79.68421  91.7  98.4 105.6000
10  93.05263 108.5 117.1 126.0000
12 108.52632 131.3 144.4 151.4000
14 123.38889 141.9 164.5 161.8000
16 144.64706 164.7 197.4 182.0000
18 158.94118 187.7 233.1 202.9000
20 170.41176 205.6 258.9 233.8889
21 177.75000 214.7 270.3 238.5556

您也可以使用 data.tabledplyr,但您需要重塑这些结果才能获得 2D(或 3D)格式:

library(data.table)
DT <- data.table(ChickWeight)[, mean(weight), by=.(Time, Diet)]
dcast.data.table(DT, Time ~ Diet)

或者,正如 Arun 指出的那样(这里我们只使用普通数据框):

reshape2::dcast(ChickWeight, Time ~ Diet, value.var="weight", fun.aggregate=mean)

很多 R 分析涉及熟悉 "long format" 中的数据(在我们 dcast 之前参见 DT),其中维度由列表示。

使用dplyr/tidyr

library(dplyr)
library(tidyr)
ChickWeight %>% 
       group_by(Time, Diet) %>% 
       summarise(weight=mean(weight)) %>%
       spread(Time, weight)