在使用dplyr对数据进行分组后,使用t.test函数进行汇总统计。

5
library(dplyr)
library(ggplot2)
library(magrittr)

diamonds %>% 
  group_by(cut) %>% 
  summarise(price_avg = t.test(
    . %>% filter(color == "E") %$% price,
    . %>% filter(color == "I") %$% price )$p.value)

我尝试通过分组来获取t.test的结果。在这个例子中,查看相同切割时颜色价格是否有显着差异。我得到的结果是:

Error in summarise_impl(.data, dots) : 
Evaluation error: is.atomic(x) is not TRUE.

谢谢,已添加。 - pluke
2个回答

6
library(tidyverse)
library(magrittr)

diamonds %>% 
  group_by(cut) %>% 
  summarise(price_avg = t.test(price[color=="E"], price[color=="I"])$p.value)

# # A tibble: 5 x 2
#   cut       price_avg
#   <ord>         <dbl>
# 1 Fair       3.90e- 3
# 2 Good       1.46e-12
# 3 Very Good  2.44e-39
# 4 Premium    7.27e-52
# 5 Ideal      7.63e-62

您的解决方案存在问题,.将获取整个数据集而非基于分组的子集。请执行以下检查:
diamonds %>% 
  group_by(cut) %>% 
  summarise(d = list(.))

# # A tibble: 5 x 2
#     cut       d                     
#     <ord>     <list>                
#   1 Fair      <tibble [53,940 x 10]>
#   2 Good      <tibble [53,940 x 10]>
#   3 Very Good <tibble [53,940 x 10]>
#   4 Premium   <tibble [53,940 x 10]>
#   5 Ideal     <tibble [53,940 x 10]>

另一种解决方案是这样的:
diamonds %>% 
  nest(-cut) %>%
  mutate(price_avg = map_dbl(data, ~t.test(
                                      .x %>% filter(color == "E") %$% price,
                                      .x %>% filter(color == "I") %$% price )$p.value))

# # A tibble: 5 x 3
#   cut       data                  price_avg
#   <ord>     <list>                    <dbl>
# 1 Ideal     <tibble [21,551 x 9]>  7.63e-62
# 2 Premium   <tibble [13,791 x 9]>  7.27e-52
# 3 Good      <tibble [4,906 x 9]>   1.46e-12
# 4 Very Good <tibble [12,082 x 9]>  2.44e-39
# 5 Fair      <tibble [1,610 x 9]>   3.90e- 3

这在IT技术中很常见。使用filter时,你可以每次传递适当的数据子集(即列data),因此它能够正常工作。

啊,看起来我对dplyr有点过于着迷了。有没有办法在summarise()中使用filter()呢?# - pluke
2
@pluke,不太好。我认为“推荐”的方法是使用tidyr::nest + purrr + broom而不是纯dplyr。 - Konrad Rudolph
我同意@KonradRudolph的观点,但你认为在summarise中使用filter怎么样?为什么? - AntoniosK
如上所述,我想使用filter(color == "E")而不是基本的R。 - pluke
1
我不知道是否有办法仅使用 dplyr 来完成这个任务。但是请注意,问题不在于 filter 命令,而在于您无法使用正确的数据子集来进行过滤。您可以使用以下方式中的 purrrdiamonds %>% nest(-cut) %>% mutate(price_avg = map_dbl(data, ~t.test( .x %>% filter(color == "E") %$% price, .x %>% filter(color == "I") %$% price )$p.value)) - AntoniosK

6

一定有更好的方法来完成这个任务。我可能会选择Antonios的方法,但是我不想使用filter,而是将不同颜色的价格分散到列表列中。不幸的是,我能想到的最好代码结果变得更长了:

diamonds %>%
    group_by(cut, color) %>%
    summarize(price = list(price)) %>%
    spread(color, price) %>%
    nest() %>%
    mutate(price_avg = map_dbl(data, ~ t.test(.x$E[[1L]], .x$I[[1L]])$p.value))

在这里的想法是为相应颜色的钻石价格获得两个列表列,IE。我们现在可以在这两列上运行t-test(但不幸的是,我们需要将它们取消列出才能正常工作)。
我主要把这个放在这里作为一个对话的开端。显然,这不是你想编写的代码,但我相信应该有一种简短、逻辑的方法来表达这个逻辑(无论是已经可能了,我正在忽视它,还是整洁的数据API需要增强)。
或者我们可以使用t.test的公式API:
diamonds %>%
    filter(color %in% c('E', 'I')) %>%
    nest(-cut) %>%
    mutate(price_avg = map_dbl(data, ~ t.test(price ~ color, .x)$p.value))

为了完整起见,这里也介绍一下使用 broom::tidy 进行的相同操作(它返回比 p 值更多的列):

diamonds %>%
    filter(color %in% c('E', 'I')) %>%
    nest(-cut) %>%
    mutate(test = map(data, ~ tidy(t.test(price ~ color, .x)))) %>%
    unnest(test)

这将会生成一个如下所示的表格:
  cut       data             estimate estimate1 estimate2 statistic  p.value parameter conf.low conf.high method                  alternative
  <ord>     <list>              <dbl>     <dbl>     <dbl>     <dbl>    <dbl>     <dbl>    <dbl>     <dbl> <fct>                   <fct>
1 Fair      <tibble [1 × 7]>   -1003.     3682.     4685.     -2.91 3.90e- 3      327.   -1682.     -324. Welch Two Sample t-test two.sided
2 Good      <tibble [1 × 7]>   -1655.     3424.     5079.     -7.19 1.46e-12      827.   -2107.    -1203. Welch Two Sample t-test two.sided
3 Very Good <tibble [1 × 7]>   -2041.     3215.     5256.    -13.4  2.44e-39     1860.   -2339.    -1743. Welch Two Sample t-test two.sided
4 Premium   <tibble [1 × 7]>   -2407.     3539.     5946.    -15.5  7.27e-52     2405.   -2711.    -2103. Welch Two Sample t-test two.sided
5 Ideal     <tibble [1 × 7]>   -1854.     2598.     4452.    -17.0  7.63e-62     3081.   -2069.    -1640. Welch Two Sample t-test two.sided

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接