如何在R Dataframe中按ID分组从累积均值计算单个值?
解决R数据框中从累积均值反推单个测量值的问题
最近我在处理R数据框时碰到个头疼的问题:要从**累积均值(running mean)**反推出每个分组下的单个测量值。手头的原始数据是这样的:
| x | ID | Mean |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 2 | 5 |
| 2 | 1 | 3 |
| 2 | 2 | 6 |
这里的Mean列是对应ID分组下,到当前x为止的所有测量值的累积均值。我想要新增一列IndivValues,得到每个行对应的单个测量值,最终目标结果是:
| x | ID | Mean | IndivValues |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 1 | 2 | 5 | 5 |
| 2 | 1 | 3 | 5 |
| 2 | 2 | 6 | 7 |
一开始我想着按ID分组用递归函数,但纠结于apply类函数没法直接访问前一条记录,不知道该怎么下手。后来琢磨出了两种简单的实现方法,分享给大家:
方法一:用dplyr分组计算
核心思路是利用累积均值的数学公式反推:假设某个分组里第n行的累积均值是Mean_n,第n-1行的是Mean_{n-1},那么第n行的单个测量值就是:IndivValues_n = n*Mean_n - (n-1)*Mean_{n-1}
对于每个分组的第一行,n=1,所以单个值就等于它的累积均值,完美符合逻辑。
具体代码如下:
library(dplyr) # 构造示例数据框 df <- tibble( x = c(1, 1, 2, 2), ID = c(1, 2, 1, 2), Mean = c(1, 5, 3, 6) ) # 计算单个值 df <- df %>% group_by(ID) %>% mutate( # 标记每个分组内的行号,用来确定是第几个值 row_num = row_number(), # 获取前一行的Mean值,第一行默认用0 prev_mean = lag(Mean, default = 0), # 按公式计算单个测量值 IndivValues = row_num * Mean - (row_num - 1) * prev_mean ) %>% # 移除中间辅助列(如果不需要的话) select(-row_num, -prev_mean) %>% ungroup() print(df)
运行后就能得到目标结果啦。
方法二:用data.table高效处理(适合大数据)
如果你的数据量很大,data.table的分组操作会更高效,思路和上面完全一致:
library(data.table) # 构造示例数据表 dt <- data.table( x = c(1, 1, 2, 2), ID = c(1, 2, 1, 2), Mean = c(1, 5, 3, 6) ) # 计算单个值 dt[, `:=`( row_num = .I, prev_mean = shift(Mean, fill = 0) ), by = ID] dt[, IndivValues := row_num * Mean - (row_num - 1) * prev_mean] # 移除辅助列 dt[, c("row_num", "prev_mean") := NULL] print(dt)
简单解释下公式的原理:累积均值是前n个值的总和除以n,所以前n个值的总和是n*Mean_n,前n-1个值的总和是(n-1)*Mean_{n-1},两者相减就是第n个单独的测量值。这个逻辑完全覆盖了所有情况,包括分组的第一行。
内容的提问来源于stack exchange,提问作者piylo
相关产品推荐
相关产品推荐

