我正在尝试计算多个列的中值,但我的数据有点时髦。它看起来像下面的例子。
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
表格中的列表示该值的出现次数。我想计算中位数。
例如ID = 1
median(c(10, 10, 10))
是我想要创建的计算。
表示ID = 2
median(c(0, 0, 0, 0, 0, 10, 10, 20, 20))
我尝试过使用rep()
和lapply()
取得的成功非常有限,并且已经明确指出如何实现这一目标。我理解rep()
之类的内容我将不得不重复编码我的重复值(例如rep(0,2)
或rep(10,2)
),这就是我所期望的。我正在努力创建一个包含每列重复的列表或向量。
答案 0 :(得分: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
这只是试图在没有重塑的情况下获得@ eddi的答案(我倾向于将其作为最后的手段)。
答案 1 :(得分:12)
你需要一本字典来将列名翻译成相应的数字,然后它相当简单:
module.exports
答案 2 :(得分:6)
这是一种避免行间操作和重新整形的方法:
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]
给出了
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
对于循环,我借用@alexis_laz'样式,例如https://stackoverflow.com/a/30513197/
我已经跳过了列名的翻译,但这非常简单。您最后可以使用c(0,10,20)
代替names(.SD)
。
答案 3 :(得分:3)
以下是rowwise
dplyr
方式:
dt %>% rowwise %>%
do(med = median(c(rep(0, .$none), rep(10, .$ten), rep(20, .$twenty)))) %>%
as.data.frame
med
1 10
2 0
3 10
4 10
受@ Arun的回答启发,这也有效:
dt %>% group_by(ID) %>%
summarise(med = median(rep(c(0, 10, 20), c(none, ten, twenty))))
Source: local data table [4 x 2]
ID med
(dbl) (dbl)
1 1 10
2 2 0
3 3 10
4 4 10