r - 如何对 data.table 中特定列的不同子集取平均值?
问题描述
给定一个示例数据框:
dt <- data.table(value=1:10,start=c(1,4,5,8,6,3,2,1,9,4),finish=c(3,7,8,9,10,10,4,10,10,8))
我想添加一个名为 mean_column 的新列。此列的第 i 行应具有值
mean( value[ seq( from = start[i], to=finish[i] ) ] )
我正在处理的真实数据有 2000 万行,所以我需要找到一种快速的方法来进行此计算。
编辑: data.table 中的 value 列不需要是示例中的有序序列。此列中的每个值都可以采用任何正数。
解决方案
这是一种使用来自data.table的非 equi 连接的方法。
dt <- data.table(value=c(10,1:9),start=c(1,4,5,8,6,3,2,1,9,4),finish=c(3,7,8,9,10,10,4,10,10,8))
dt[, id := .I]
dt[dt,
on = .(id >= start,
id <= finish),
.(i.id, i.value, mean_col = mean(x.value)),
by = .EACHI,
allow.cartesian = T]
id id i.id i.value mean_col
<int> <int> <int> <num> <num>
1: 1 3 1 10 4.333333
2: 4 7 2 1 4.500000
3: 5 8 3 2 5.500000
4: 8 9 4 3 7.500000
5: 6 10 5 4 7.000000
6: 3 10 6 5 5.500000
7: 2 4 7 6 2.000000
8: 1 10 8 7 5.500000
9: 9 10 9 8 8.500000
10: 4 8 10 9 5.000000
在我的计算机上尝试 2,000,000 行需要 4 秒,并提供与 @jay.sf 相同的答案。
n = 2e6
dt <- data.table(value = sample(1000L, n, TRUE), start = sample(n, n, TRUE))
dt[, finish := start + sample(30, n, TRUE)]
dt[finish > n, finish := n]
system.time({
dt[, id := .I]
dt[dt,
on = .(id >= start,
id <= finish),
.(i.id, i.value, mean_col = mean(x.value)),
by = .EACHI,
allow.cartesian = T]
})
## user system elapsed
## 3.78 0.01 3.69
#jay.sf base approach
system.time({
FUNV3 <- Vectorize(function(x, y) x:y)
dt$mean.column2 <- with(dt, sapply(FUNV3(start, finish), function(x) mean(value[x])))
})
## user system elapsed
## 24.45 0.04 24.72
all.equal(dt$mean.column2, dt[dt,
on = .(id >= start,
id <= finish),
.(i.id, i.value, mean_col = mean(x.value)),
by = .EACHI,
allow.cartesian = T]$mean_col)
##[1] TRUE
推荐阅读
- haskell - 使用 GHC 插件解析类型
- python - 在绘图选择上过滤散景数据表
- python - 在避免多处理python中的内存泄漏后会删除一个变量并重新创建它吗?
- mongodb - 联系人的 MongoDB Schema 优化
- python-3.x - numpy.genfromtxt() 无法读取标题
- javascript - 在 React JS 中更改子属性的位置
- java - SharedPreferences 未保存在 EditTexts 中
- javascript - 如何访问其他js文件的express模块,express模块已经包含在app.js中
- python - 使用其他表单元素在烧瓶中上传文件失败并出现 400 错误
- gradle - 如何正确运行 gradle 测试任务?