data.table:计算百分所有数值变量
我的数据是这样data.table:计算百分所有数值变量
set.seed(1)
dt <- data.table(id = c("A", "A", "B", "B","C", "C"),
var1 = c(1:6),
var2 = rnorm(6))
> dt
id var1 var2
1: A 1 -0.6264538
2: A 2 0.1836433
3: B 3 -0.8356286
4: B 4 1.5952808
5: C 5 0.3295078
6: C 6 -0.8204684
但与几十个数字变量的。我想使用data.table
来计算每个观测值和每个数值变量的百分位数,同时保持密钥标识符(id
)完好无损。在dplyr
我能做到这一点是这样的:
mutate_if(dt, is.numeric, function(x) { ecdf(x)(x) })
id var1 var2
1 A 0.1666667 0.5000000
2 A 0.3333333 0.6666667
3 B 0.5000000 0.1666667
4 B 0.6666667 1.0000000
5 C 0.8333333 0.8333333
6 C 1.0000000 0.3333333
我也将是高兴的结果,包括原var1
和var2
。
什么是最好的方法来解决这个问题?
感谢您的帮助!
你可以计算ecdf
所有数字列在这样一个单独的数据表:
dt2 = as.data.table(lapply(dt,function(x){if(is.numeric(x)){ecdf(x)(x)}}))
结果:
> dt2
var1 var2
1: 0.1666667 0.8333333
2: 0.3333333 0.3333333
3: 0.5000000 0.6666667
4: 0.6666667 1.0000000
5: 0.8333333 0.1666667
6: 1.0000000 0.5000000
如果你想cbind
这个结果原来的DT,你可以使用paste0
更改列名称:
colnames(dt2) = paste0("centile_",colnames(dt2))
结果:
> dt2
centile_var1 centile_var2
1: 0.1666667 0.8333333
2: 0.3333333 0.3333333
3: 0.5000000 0.6666667
4: 0.6666667 1.0000000
5: 0.8333333 0.1666667
6: 1.0000000 0.5000000
谢谢!它几乎正是我所需要的:你的结果不包含'id',如果我简单地尝试'cbind',它会得到与原始数据不同的结果。有没有办法将结果保留下来? –
只需在末尾添加'else'语句:'as.data.table(lapply(dt,function(x){if(is.numeric(x)){ecdf(x)(x)} else x}) )'。 – lmo
@lmo,谢谢你的帮助! –
没有时间解释,但是这应该给你想要的东西没有ID列:'DT [,lapply(.SD,函数(X)ECDF(X)(X)) ,.SDcols = sapply(dt,is.numeric)]'。然后你可以在后面加上id列。 – jav
尝试mutate_at(dat,vars(starts_with(“var”)),function(x){ecdf(x)(x)})或mutate_if(dat,is.numeric,function(x){ecdf(x )(x)})' –
@jav,有没有一种方法在结果中保留'id'?由于某种原因,简单的绑定给我的结果与原始数据相比是不准确的 –