Как я могу рассчитать средний интервал процентиля в R без использования цикла?

У меня есть набор данных с разными группами - для этого примера давайте просто скажем две группы - и я хочу рассчитать средний процентный ранг, но я хочу использовать 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), но ни один из них не дал того, что я ищу. Любые идеи были бы хорошы.


person user3782782    schedule 12.07.2014    source источник
comment
Извините - я показываю свой статус новичка, но когда я пытаюсь обработать значения NA, формула выше ломается! Кажется, я получаю строку символов, а не вектор. если немного изменить данные: group ‹-c (A, A, A, A, A, A, A, A, A, A, A, B, B, B, B, B, B, B, B, B , B, C, B) оценка ‹-c (1,2,3,4,5,6,7,8,9,10,10,9,10,7,8,4,5,10,11, 12,., 10); оценка превращается в фактор. Я могу исправить эту оценку ‹-as.numeric (as.character (score)); но функция сейчас не работает. Я могу удалить NA; orig ‹-data.frame (группа, оценка) delt‹ -data.frame (orig [! is.na (orig $ score),]); Есть идеи, где я ошибаюсь?   -  person user3782782    schedule 23.07.2014


Ответы (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
person jlhoward    schedule 12.07.2014
comment
Спасибо. Два красивых решения! Оба предоставят мне много возможностей для работы, чтобы разобраться (я немного новичок). Я надеялся запустить это в вызове dplyr, так как это одна из многих вещей, которые я пытаюсь сделать. Хотя в dplyr есть команда do (), я не понимаю, как использовать текущую функцию с помощью do (). Есть другие предложения? - person user3782782; 12.07.2014