Dan*_*Dan 14 r lapply rep data.table
我试图计算多个列的中值,但我的数据有点时髦.它看起来像下面的例子.
library(data.table)
dt <- data.table("ID" = c(1,2,3,4),"none" = c(0,5,5,3),
"ten" = c(3,2,5,4),"twenty" = c(0,2,3,1))
ID none ten twenty
1: 1 0 3 0
2: 2 5 2 2
3: 3 5 5 3
4: 4 3 4 1
Run Code Online (Sandbox Code Playgroud)
在表中,列表示该值的出现次数.我想计算中位数.
例如,对于ID = 1
median(c(10, 10, 10))
Run Code Online (Sandbox Code Playgroud)
是我想要创建的计算.
对于ID = 2
median(c(0, 0, 0, 0, 0, 10, 10, 20, 20))
Run Code Online (Sandbox Code Playgroud)
我尝试过使用rep()并lapply()取得了非常有限的成功,并且已经就如何实现这一目标提供了明确的指导.我理解为喜欢rep()我将不得不硬编码我的价值重复(例如rep(0,2)或rep(10,2)),这是我所期望的.我正在努力创建一个包含每列重复的列表或向量.
Aru*_*run 16
这是另一种data.table方式(假设是唯一的ID):
dt[, median(rep(c(0, 10, 20), c(none, ten, twenty))), by=ID]
# ID V1
# 1: 1 10
# 2: 2 0
# 3: 3 10
# 4: 4 10
Run Code Online (Sandbox Code Playgroud)
这只是试图获得@ eddi的答案而不重塑(我倾向于使用它作为最后的手段).
edd*_*ddi 12
您需要一个字典来将列名转换为相应的数字,然后它非常简单:
dict = data.table(name = c('none', 'ten', 'twenty'), number = c(0, 10, 20))
melt(dt, id.var = 'ID')[
dict, on = c(variable = 'name')][, median(rep(number, value)), by = ID]
# ID V1
#1: 1 10
#2: 2 0
#3: 3 10
#4: 4 10
Run Code Online (Sandbox Code Playgroud)
这是一种避免行间操作和重新整形的方法:
dt[, m := {
cSD = Reduce(`+`, .SD, accumulate=TRUE)
k = floor(cSD[[length(.SD)]]/2)
m = integer(.N)
for(i in seq_along(cSD)) {
left = m == 0L
if(!any(left)) break
m[left] = i * (cSD[[i]][left] >= k[left])
}
names(.SD)[m]
}, .SDcols=none:twenty]
Run Code Online (Sandbox Code Playgroud)
这使
ID none ten twenty m
1: 1 0 3 0 ten
2: 2 5 2 2 none
3: 3 5 5 3 ten
4: 4 3 4 1 ten
Run Code Online (Sandbox Code Playgroud)
对于循环,我借用@alexis_laz'样式,例如/sf/answers/2135923821/
我已经跳过了列名的翻译,但这非常简单.你可以使用c(0,10,20)而不是names(.SD)在最后.
| 归档时间: |
|
| 查看次数: |
8913 次 |
| 最近记录: |