使用dplyr窗口函数来计算百分位数
我有一个可行的解决方案,但我正在寻找更清晰,更易读的解决方案,可能会利用一些较新的dplyr窗口功能。
使用mtcars数据集,如果我想查看第25,50和75百分位数以及汽缸数(“cyl”)的每加仑英里数(“mpg”)的平均值和计数,我使用以下代码:
library(dplyr)
library(tidyr)
# load data
data("mtcars")
# Percentiles used in calculation
p <- c(.25,.5,.75)
# old dplyr solution
mtcars %>% group_by(cyl) %>%
do(data.frame(p=p, stats=quantile(.$mpg, probs=p),
n = length(.$mpg), avg = mean(.$mpg))) %>%
spread(p, stats) %>%
select(1, 4:6, 3, 2)
# note: the select and spread statements are just to get the data into
# the format in which I'd like to see it, but are not critical
有没有一种方法可以使用dplyr使用某些汇总函数(n_tiles,percent_rank等)更干净地执行此操作? 干净,我的意思是没有“做”声明。
谢谢
如果你想使用purrr::map
,你可以这样做!
library(dplyr)
library(tidyr)
library(broom)
library(purrr)
mtcars %>%
nest(-cyl) %>%
mutate(Quantiles = map(data, ~ quantile(.$mpg))) %>%
unnest(map(Quantiles, tidy))
#> # A tibble: 15 × 3
#> cyl names x
#> <dbl> <chr> <dbl>
#> 1 6 0% 17.80
#> 2 6 25% 18.65
#> 3 6 50% 19.70
#> 4 6 75% 21.00
#> 5 6 100% 21.40
#> 6 4 0% 21.40
#> 7 4 25% 22.80
#> 8 4 50% 26.00
#> 9 4 75% 30.40
#> 10 4 100% 33.90
#> 11 8 0% 10.40
#> 12 8 25% 14.40
#> 13 8 50% 15.20
#> 14 8 75% 16.25
#> 15 8 100% 19.20
这种方法的一个好处是输出是整齐的,每行一个观察值。
这是一个dplyr
方法,可以避免do
但需要单独调用quantile
来计算每个分位数值。
mtcars %>% group_by(cyl) %>%
summarise(`25%`=quantile(mpg, probs=0.25),
`50%`=quantile(mpg, probs=0.5),
`75%`=quantile(mpg, probs=0.75),
avg=mean(mpg),
n=n())
cyl 25% 50% 75% avg n
1 4 22.80 26.0 30.40 26.66364 11
2 6 18.65 19.7 21.00 19.74286 7
3 8 14.40 15.2 16.25 15.10000 14
如果summarise
可以通过一次调用quantile
来返回多个值,那将会更好,但这似乎是dplyr
开发中的一个公开问题。
更新:这是@ JuliaSilge的答案的变体,它使用嵌套获取分位数,但不使用map
。 但是,它确实需要额外的代码行来添加列出分位数级别的列,因为我不知道如何(或者如果可能的话)直接从quantile
调用中将分位数的名称捕获到单独的列中。
p = c(0.25,0.5,0.75)
mtcars %>%
group_by(cyl) %>%
summarise(quantiles = list(sprintf("%1.0f%%", p*100)),
mpg = list(quantile(mpg, p))) %>%
unnest
cyl quantiles mpg
1 4 25% 22.80
2 4 50% 26.00
3 4 75% 30.40
4 6 25% 18.65
5 6 50% 19.70
6 6 75% 21.00
7 8 25% 14.40
8 8 50% 15.20
9 8 75% 16.25
这是一种使用broom
包的tidy()
函数的dplyr
方法,但不幸的是它仍然需要do()
,但它要简单得多。
library(dplyr)
library(broom)
mtcars %>%
group_by(cyl) %>%
do( tidy(t(quantile(.$mpg))) )
这使:
cyl X0. X25. X50. X75. X100.
(dbl) (dbl) (dbl) (dbl) (dbl) (dbl)
1 4 21.4 22.80 26.0 30.40 33.9
2 6 17.8 18.65 19.7 21.00 21.4
3 8 10.4 14.40 15.2 16.25 19.2
请注意使用t()
因为broom
包没有命名数字的方法。
这是基于我以前对summary()的回答。
链接地址: http://www.djcxy.com/p/24837.html上一篇: Using dplyr window functions to calculate percentiles
下一篇: How to make a reproducible example of a database connection?