2017-02-10 2 views
1

Я хочу найти децили для каждой сгруппированной переменной. Я специально ищу методы, используя dplyr и lapply. Буду признателен, если вы сможете мне помочь.Децили по групповой переменной в R

Вот мои, что я пробовал. Я не знаю, как вытащить децилями непосредственно, кроме вызова dplyr::ntile() (который не работает для меня)

Покушение 1

Вот что я попытался с помощью describe() из Hmisc пакета:

set.seed(10) 
IData <- data.frame(let = sample(x = LETTERS, size = 10000, replace=TRUE), numbers = sample(x = c(1:20000),size = 10000)) 

Output<-IData %>% data.table::as.data.table(.) %>% split(.,by=c("let"),drop = TRUE,sorted = TRUE) %>% purrr::map(~describe(.$numbers)) 

Это, безусловно, помогает, но есть две проблемы с вышеуказанным кодом:

a) Выход (даже формат списка) не является тем, что я ищу.

b) Я действительно не знаю, как извлечь 5%, 10% ... из списка выше.

Bottomline, что я застрял

Покушение 2

Я попытался заменить describe на ntile, но следующий код дал мне выход, который не имеет смысла для меня, потому что числа столбцы не 10. После запуска Output[[1]], я вижу вектор ~ 400 чисел вместо 10.

Output<-IData %>% data.table::as.data.table(.) %>% split(.,by=c("let"),drop = TRUE,sorted = TRUE) %>% purrr::map(~dplyr::ntile(.$numbers,10)) 

Попытка 3 = Ожидаемый результат

Наконец, я попытался перейти в старую школу (т. копипаст), чтобы получить ожидаемый результат:

Output<-IData %>% 
    dplyr::group_by(let) %>% 
    dplyr::summarise(QQuantile1 = quantile(`numbers`, c(.10)), 
        QQuantile1 = quantile(`numbers`, c(.10)), 
        QQuantile2 = quantile(`numbers`, c(.20)), 
        QQuantile3 = quantile(`numbers`, c(.30)), 
        QQuantile4 = quantile(`numbers`, c(.40)), 
        QQuantile5 = quantile(`numbers`, c(.50)), 
        QQuantile6 = quantile(`numbers`, c(.60)), 
        QQuantile7 = quantile(`numbers`, c(.70)), 
        QQuantile8 = quantile(`numbers`, c(.80)), 
        QQuantile9 = quantile(`numbers`, c(.90)), 
        QQuantile10 = quantile(`numbers`, c(.100))) 

Вопрос: Может кто-то пожалуйста, помогите мне, чтобы произвести выше вывод, используя эти три (а не один, а предпочтительно все методы обучения)

1) lapply

2) dplyr

3) data.table

Я смотрел на несколько ниток s on SO, но все они говорят о конкретном квантиле, и не все из них. Например. Find top deciles from dataframe by group нить.

+2

'library (tidyverse); IData%>% group_by (let)%>% sumize (quant_prob = list (paste0 ('quant', seq (.1, 1, .1))), quant_value = list (quantile (числа, seq (.1, 1) , .1))))%>% unpest()%>% spread (quant_prob, quant_value) 'возможно, хотя, вероятно, более полезно оставить его в длинной форме – alistaire

+0

@Alistaire - Спасибо за вашу помощь. Как вы думаете, вы могли бы также помочь мне с версией 'lapply' и' Data.Table', чтобы я мог изучить новые способы решения одной и той же проблемы? – watchtower

+1

Хм, по-видимому, база R думает так же, как и вы: 'aggregate (numbers ~ let, IData, quantile, seq (.1, 1, .1))' – alistaire

ответ

4

Чтобы собрать свои комментарии в ответ, база поразительно прост:

aggregate(numbers ~ let, IData, quantile, seq(0.1, 1, 0.1)) 

## let numbers.10% numbers.20% numbers.30% numbers.40% numbers.50% numbers.60% numbers.70% numbers.80% ... 
## 1 A  1749.8  3847.8  5562.6  7475.2  9926.0  11758.6  13230.6  15788.8 
## 2 B  2393.5  4483.6  6359.1  7708.0  9773.0  11842.8  13468.9  16266.4 
## 3 C  2041.5  3682.0  5677.5  7504.0  9226.0  11470.0  13628.5  15379.0 
## 4 D  1890.7  4086.8  5661.9  7526.6  9714.0  11438.8  13969.2  15967.2 
## 5 E  2083.6  4107.0  6179.8  7910.8  10095.0  11692.6  13668.0  15570.2 
## 6 F  1936.6  4220.2  6197.0  8791.8  10382.0  12266.4  14589.2  16407.0 
## 7 G  3059.4  4884.2  6519.6  8530.0  10481.0  12469.0  14401.6  16127.8 
## 8 H  2186.5  4081.0  5801.5  7206.0  9256.5  11453.0  13692.0  15471.0 
## 9 I  1534.1  3793.2  5822.2  7621.4  9417.5  11737.0  14191.2  15722.4 
## 10 J  1967.2  4286.6  5829.6  7664.6  10606.0  12217.4  14422.2  16628.0 
## ... 

dplyr работает, если вы используете список столбцов или do и перекроить:

library(tidyverse) 

IData %>% group_by(let) %>% 
    summarise(quant_prob = list(paste0('quant', seq(.1, 1, .1))), 
       quant_value = list(quantile(numbers, seq(.1, 1, .1)))) %>% 
    unnest() %>% 
    spread(quant_prob, quant_value) 

## # A tibble: 26 × 11 
##  let quant0.1 quant0.2 quant0.3 quant0.4 quant0.5 quant0.6 quant0.7 quant0.8 quant0.9 quant1 
## * <fctr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
## 1  A 1749.8 3847.8 5562.6 7475.2 9926.0 11758.6 13230.6 15788.8 17763.0 19958 
## 2  B 2393.5 4483.6 6359.1 7708.0 9773.0 11842.8 13468.9 16266.4 17877.4 19929 
## 3  C 2041.5 3682.0 5677.5 7504.0 9226.0 11470.0 13628.5 15379.0 17265.0 19876 
## 4  D 1890.7 4086.8 5661.9 7526.6 9714.0 11438.8 13969.2 15967.2 17961.0 19989 
## 5  E 2083.6 4107.0 6179.8 7910.8 10095.0 11692.6 13668.0 15570.2 18011.4 19887 
## 6  F 1936.6 4220.2 6197.0 8791.8 10382.0 12266.4 14589.2 16407.0 18345.0 19997 
## 7  G 3059.4 4884.2 6519.6 8530.0 10481.0 12469.0 14401.6 16127.8 18219.2 19922 
## 8  H 2186.5 4081.0 5801.5 7206.0 9256.5 11453.0 13692.0 15471.0 17331.0 19996 
## 9  I 1534.1 3793.2 5822.2 7621.4 9417.5 11737.0 14191.2 15722.4 17706.6 19965 
## 10  J 1967.2 4286.6 5829.6 7664.6 10606.0 12217.4 14422.2 16628.0 18091.2 19901 
## # ... with 16 more rows 

Еще один интересный вариант purrr::by_slice, который позволяет собирать результаты столбцам:

IData %>% group_by(let) %>% 
    by_slice(~quantile(.x$numbers, seq(0.1, 1, 0.1)), .collate = "cols") 

## # A tibble: 26 × 11 
##  let .out1 .out2 .out3 .out4 .out5 .out6 .out7 .out8 .out9 .out10 
## <fctr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
## 1  A 1749.8 3847.8 5562.6 7475.2 9926.0 11758.6 13230.6 15788.8 17763.0 19958 
## 2  B 2393.5 4483.6 6359.1 7708.0 9773.0 11842.8 13468.9 16266.4 17877.4 19929 
## 3  C 2041.5 3682.0 5677.5 7504.0 9226.0 11470.0 13628.5 15379.0 17265.0 19876 
## 4  D 1890.7 4086.8 5661.9 7526.6 9714.0 11438.8 13969.2 15967.2 17961.0 19989 
## 5  E 2083.6 4107.0 6179.8 7910.8 10095.0 11692.6 13668.0 15570.2 18011.4 19887 
## 6  F 1936.6 4220.2 6197.0 8791.8 10382.0 12266.4 14589.2 16407.0 18345.0 19997 
## 7  G 3059.4 4884.2 6519.6 8530.0 10481.0 12469.0 14401.6 16127.8 18219.2 19922 
## 8  H 2186.5 4081.0 5801.5 7206.0 9256.5 11453.0 13692.0 15471.0 17331.0 19996 
## 9  I 1534.1 3793.2 5822.2 7621.4 9417.5 11737.0 14191.2 15722.4 17706.6 19965 
## 10  J 1967.2 4286.6 5829.6 7664.6 10606.0 12217.4 14422.2 16628.0 18091.2 19901 
## # ... with 16 more rows 

хотя имена столбцов немного паршиво.

+0

Мне очень нравятся ваши глубокие знания о R. Как вы думаете, включить версию 'lapply'? Я новичок в R, и я действительно хочу освоить 'lapply'. Я искренне ценю вашу помощь. – watchtower

+3

'lapply' не группируется, поэтому здесь не очень полезно. Вы можете использовать 'tapply', например' do.call (rbind, tapply (IData $ numbers, IData $ let, quantile, seq (.1, 1, .1))) '(который возвращает матрицу вместо данных. кадр), но на самом деле версия 'aggregate' является наиболее подходящей базой R-подхода. – alistaire

3

Мы можем сделать это в компактном виде с data.table. Преобразуйте данные data.frame в 'data.стол»(setDT(IData)), сгруппированных по„пусть“, получить quantile из„чисел“и преобразовать его в list (as.list)

library(data.table) 
setDT(IData)[, as.list(quantile(numbers, seq(.1, 1, .1))), by = let] 
Смежные вопросы