我有一组具有不同组的数据 - 对于这个例子,我们只说两组 - 我想计算一个中间区间百分位数,但我想使用dplyr
(所以没有循环)。
以下是我的数据和目前的情况:
library(dplyr);
group<-c("A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B")
score<-c(1,2,3,4,5,6,7,8,9,10,10,9,10,7,8,4,5,10,11,12,13,10)
my_orig_df<-data.frame(group,score)
mydf<-my_orig_df %.%
group_by(group) %.%
mutate ( Cum= round( cume_dist(score),2) , myPTILE=percent_rank(score))
mydf
要清楚,我希望组A
的第一个值为.05,而不是.09,也不是0。
虽然结果很接近,但它们并不完全符合我的预期。
我可以通过嵌套循环获得所需的结果(但这不是我想要的):
Ugroup<-unique (group)
for (i in 1:length(Ugroup)) {
temp<-subset(mydf,group==Ugroup[i])
for(j in 1:length(temp$score)) {
ptile<-c(ptile, ((sum(temp$score==temp$score[j])/2)+sum(temp$score<temp$score[j])) /length(temp$score))
} }
当我使用带有多个组的大型数据集的循环(上面)运行代码时,时间就成了问题。
我尝试了以下内容:row_number(score); ntile(score, 99); min_rank(score); dense_rank(score); percent_rank(score); cume_dist(score)
但没有一个会导致我正在寻找的内容。任何想法都将不胜感激。
答案 0 :(得分:1)
这似乎与你的循环产生相同的东西。虽然不使用dplyr
f <- function(z) sapply(z,function(x) (sum(z==x)/2+sum(z<x))/length(z))
ptile <- as.vector(t(aggregate(score~group,my_orig_df,f)[,-1]))
ptile
# [1] 0.04545455 0.13636364 0.22727273 0.31818182 0.40909091 0.50000000 0.59090909
# [8] 0.68181818 0.77272727 0.90909091 0.90909091 0.40909091 0.59090909 0.22727273
# [15] 0.31818182 0.04545455 0.13636364 0.59090909 0.77272727 0.86363636 0.95454545
# [22] 0.59090909
这是一个可能更快的data.table解决方案。
library(data.table)
DT <- as.data.table(my_orig_df)
ptile.dt <- DT[,sapply(score,function(x)(sum(score==x)/2+sum(score<x))/.N),by=group]$V1
identical(ptile,ptile.dt)
# [1] TRUE