2016-12-11 16 views
1

Этот вопрос является расширением для заданного вопроса StackOverflow и ответа here.Эффективно вычислять процентиль столбца DataFrame

Мои обстоятельства отличаются тем, что я хочу рассчитать процентиль каждого значения в векторе из 50 000 (или более!) Значений. Например,

df <- data.frame(val = rnorm(n = 50000, mean = 50, sd = 20)) 
df$val.percentile <- sapply(X = df$val, function(x) ecdf(df$val)(x)) 
head(df) 

Есть ли хороший способ оптимизировать процесс вычисления процентиля для каждого значения? По сути, я хотел бы сделать его максимально эффективным, чтобы время работы было как можно меньше.

ответ

2

Вы можете реализовать dplyr::percent_rank, чтобы ранжировать каждое значение на основе процентиля.

df.per <- df %>% 
    mutate(val.percentile = percent_rank(val)) 

Редактировать

Я считаю @ 42 имеет лучший вариант на этот вопрос. Опасность OP заключалась в больших наборах данных. В то время как dplyr::percent_rank очень быстрый, ответ на 42 намного быстрее.

я увеличил количество строк до 1000000 и побежал следующий код:

df <- data.frame(val = rnorm(n = 1000000, mean = 50, sd = 20)) 

Мой первоначальный ответ:

t <- proc.time() 
df <- df %>% 
    mutate(val.percentile = percent_rank(val)) 
proc.time() - t 


user system elapsed 
2.484 0.068 2.554 

@ 42 в ответ:

t <- proc.time() 
df$val.percentile.2 <- ecdf(df$val)(df$val) 
proc.time() - t 


user system elapsed 
1.048 0.004 1.048 

Так ясно ecdf выполняет гораздо лучше в данном контексте. Результаты val.percentile и val.percentile.2 практически идентичны.

4

ecdf уже векторизован, нет оснований использовать функцию apply. Вы можете просто запустить:

df$val.percentile <- ecdf(df$val)(df$val) 
+0

Как этот ответ отличался от моего? –

+0

@ 42- Это не так, но вы и Баркер выложили почти в то же время (с первым Баркером) – Jaap

+0

Да, я не видел его, когда отправлял (или редактировал). Я предполагал, что это произошло позже. –