在R中按ID分组处理时间数据并添加score二值列的方法
问题描述
现有包含inst、ID、time_B字段的数据集(示例数据如下),其中ID代表不同的鱼。需求为新增名为score的列:若该行的time_B占对应ID总时间的50%以上则赋值1,否则赋值0。此前使用aggregate函数(aggregate(B ~ fish_ID, data = allBlue, mean))计算每个ID的均值,但需要适配大数据集的高效实现方案。
示例数据集
| inst | ID | time_B |
|---|---|---|
| 0 | 1 | 136 |
| 1 | 1 | 245 |
| 2 | 1 | 64 |
| 3 | 1 | 510 |
| 0 | 14 | 115 |
| 1 | 14 | 491 |
| 2 | 14 | 186 |
| 3 | 14 | 265 |
| 0 | 4 | 131 |
| 1 | 4 | 300 |
| 2 | 4 | 254 |
| 3 | 4 | 284 |
高效实现方案
针对大数据集,推荐使用data.table或dplyr包,二者均通过向量化分组操作实现高效计算,远优于base R的aggregate函数。
方案1:使用data.table
data.table专为大数据处理优化,内存占用低、运算速度快:
# 加载包 library(data.table) # 将数据集转换为data.table(若原数据是data.frame) dt <- as.data.table(your_data) # 分组计算每个ID的总时间,新增score列 dt[, total_time := sum(time_B), by = ID] dt[, score := as.integer(time_B / total_time > 0.5)] # 可选:删除临时的total_time列 dt[, total_time := NULL]
方案2:使用dplyr(tidyverse生态)
dplyr代码可读性高,适合习惯tidy语法的用户,同样支持高效分组操作:
# 加载包 library(dplyr) # 分组计算并新增score列 your_data <- your_data %>% group_by(ID) %>% mutate(total_time = sum(time_B), score = as.integer(time_B / total_time > 0.5)) %>% ungroup() %>% select(-total_time) # 可选:移除临时列
关键说明
- 两个方案均直接在原数据集上进行分组计算,避免了
aggregate需要合并结果的额外开销 as.integer()将布尔值(TRUE/FALSE)转换为1/0,满足score列的赋值需求- 若数据集规模极大,data.table的性能优势会更明显;dplyr则胜在代码简洁易维护
内容的提问来源于stack exchange,提问作者Balina
相关产品推荐
相关产品推荐

