首页 > 解决方案 > 在汇总中创建多个列

问题描述

summarize(...)在(或者,在)中创建多个列的最佳方法是什么do(...)?如果某个聚合函数返回多个值,就会出现这种情况。这种函数的一个例子是quantile(...)

例如,假设我们有以下数据

library(dplyr)

data.frame(x = runif(1000, min = 0, max = 20)) %>%
  mutate(y = rnorm(n(), mean = sin(x))) %>%
  group_by(x.category = round(x)) ->
  Z

我们可以很容易地计算(和绘制)分位数:

library(ggplot2) # just to display results (not the focus of this question)

Z %>%
  summarize(x = mean(x),
            y25 = quantile(y, probs = .25),
            y50 = quantile(y, probs = .5),
            y75 = quantile(y, probs = .75)) %>%
  gather(Statistic, y, -x, -x.category) %>%
  ggplot(aes(x, y, color = Statistic)) +
  geom_line()

但是,上面的代码有两个缺点:1)quantile(...)代码必须重复(如果需要十几个分位数,这将变得更加乏味),以及 2)列名(y25、y50、y75)可能与实际分位数。

这些问题可以通过利用quantile(...)计算多个分位数并将它们返回到带有名称的向量中的能力来解决,如下所示:

Z %>%
  do(as_data_frame(c(x = mean(.$x),
                     as.list(quantile(.$y, probs = c(.25,.5,.75)))))) %>%
  gather(Statistic, y, -x, -x.category) %>%
  ggplot(aes(x, y, color = Statistic)) +
  geom_line()

但是上面的代码对我来说似乎很难看;特别是它需要as.list(...), c(...), as_data_frame(...), anddo(...)才能做一些非常简单的事情。

有没有更好的办法?

标签: rdplyr

解决方案


处理返回多个值的函数时,一种可能的方法是通过组合这些值来创建一个字符串,然后使用相应的名称将该字符串分成多个列。

library(dplyr)
library(tidyr)

data.frame(x = runif(1000, min = 0, max = 20)) %>%
  mutate(y = rnorm(n(), mean = sin(x))) %>%
  group_by(x.category = round(x)) ->
  Z

# specify quantiles
q = c(0.25, 0.5, 0.75)

Z %>%
  summarise(x = mean(x),
            qtls = paste(quantile(y, q), collapse = ",")) %>%   # get quantile values as a string
  separate(qtls, paste0("y_", 100*q), sep = ",", convert = T)   # separate quantile values and give corresponding names to columns

# # A tibble: 21 x 5
#   x.category     x   y_25   y_50    y_75
#        <dbl> <dbl>  <dbl>  <dbl>   <dbl>
# 1          0 0.252 -0.596  0.156  0.977 
# 2          1 0.929 -0.191  0.753  1.15  
# 3          2 2.07   0.222  0.787  1.26  
# 4          3 2.95  -0.488  0.303  1.13  
# 5          4 3.92  -1.38  -0.627 -0.0220
# 6          5 4.94  -1.52  -1.08  -0.489 
# 7          6 6.03  -0.950 -0.432  0.492 
# 8          7 6.97  -0.103  0.602  1.32  
# 9          8 7.94   0.350  1.02   1.88  
# 10         9 9.00  -0.155  0.393  1.02  
# # ... with 11 more rows

推荐阅读