使用 map() 将测试 (Jarque-Bera) 应用于子组

Apply test (Jarque-Bera) to subgroups with map()

我正在尝试 运行 对我的数据集的子组进行测试 (Jarque-Bera)。我正在尝试为此使用 purrrs 函数 map(),但不知何故它对我来说失败了。

对于此处的示例,我将使用内置的 ChickWeight 数据集:

加载一些包:

library(dplyr)
library(ggplot2)
library(tidyr)
library(purrr)
library(tseries)

数据如下所示:

ggplot(ChickWeight, aes(weight, fill = Diet)) +
  geom_histogram() +
  facet_wrap(~Diet)

我现在正在尝试对子组饮食 1、2、3 和 4 使用 Jarque-Bera 测试。

我知道如何在这样的一组中使用它:

ChickWeight %>% 
  filter(Diet == 1) %>% 
  pull(weight) %>% 
  jarque.bera.test()

哪个returns:

    Jarque Bera Test

data:  .
X-squared = 46.687, df = 2, p-value = 7.278e-11

但是现在,我想对所有子组都这样做。所以我像这样嵌套数据:

nst <- ChickWeight %>% 
  nest(-Diet)

现在我想我可以立即应用 purrrs map() 功能,但有些失败:

tsts <- nst %>% 
  map(jb = map(data, jarque.bera.test(weight)))

哪个returns:

Error in as_mapper(.f, ...) : argument ".f" is missing, with no default

我也试过:

tsts <- nst %>% 
  mutate(jb = map(data, jarque.bera.test(weight)))

这会产生:

Error in mutate_impl(.data, dots) : Evaluation error: object 'weight' not found.

你的对象nst是一个数据框;在引擎盖下,数据框是列列表。因此,如果您将 map 应用于 nst,它将映射到列而不是映射到数据中的组。另外,请注意 map 的第二个参数必须是一个函数(或一些其他类型的 shorthand 函数表达式——请参阅 purrr::map 的文档)。

有很多方法可以解决您的问题。我最喜欢的是使用 dplyr 中的 group_bydo 以及 broom 中的 tidy:

library(dplyr)
library(tidyr)
library(purrr)
library(tseries)
library(broom)

ChickWeight %>%
    group_by(Diet) %>%
    do(tidy(jarque.bera.test(.$weight)))
# # A tibble: 4 x 5
# # Groups:   Diet [4]
#   Diet  statistic  p.value parameter method          
#   <fct>     <dbl>    <dbl>     <dbl> <fct>           
# 1 1         46.7  7.28e-11         2 Jarque Bera Test
# 2 2         18.8  8.36e- 5         2 Jarque Bera Test
# 3 3         12.4  2.00e- 3         2 Jarque Bera Test
# 4 4          5.17 7.54e- 2         2 Jarque Bera Test

请注意,tidy 获取 jarque.bera.test 的输出并将其转换为单行数据框,并通过 do 函数对每个组重复此操作。这是一个纯粹的 dplyr 方法:

ChickWeight %>%
    group_by(Diet) %>%
    summarize(p.value = jarque.bera.test(weight)$p.value)
# # A tibble: 4 x 2
#   Diet   p.value
#   <fct>    <dbl>
# 1 1     7.28e-11
# 2 2     8.36e- 5
# 3 3     2.00e- 3
# 4 4     7.54e- 2

接下来是使用 nestmap 的方法。请注意,nest 创建的数据框的第二列是列表列。我们使用 pull 仅提取列表列,然后使用 map 对每个组执行 Jarque-Bera 测试。

ChickWeight %>%
    nest(-Diet) %>%
    pull(data) %>%
    map(~ jarque.bera.test(.$weight))
# [[1]]
# 
#   Jarque Bera Test
# 
# data:  .$weight
# X-squared = 46.687, df = 2, p-value = 7.278e-11
# 
# 
# [[2]]
# 
#   Jarque Bera Test
# 
# data:  .$weight
# X-squared = 18.779, df = 2, p-value = 8.36e-05
# 
# 
# [[3]]
# 
#   Jarque Bera Test
# 
# data:  .$weight
# X-squared = 12.426, df = 2, p-value = 0.002003
# 
# 
# [[4]]
# 
#   Jarque Bera Test
# 
# data:  .$weight
# X-squared = 5.1686, df = 2, p-value = 0.07545

请注意,map 接受公式作为编写 anonymous function 的一种紧凑方式。最后,这里有一些比较笨拙的方法,它们结合了 mapdplyr:

map(1:4, ~ filter(ChickWeight, Diet == .) %>% pull(weight) %>% jarque.bera.test)

map(1:4, ~ filter(ChickWeight, Diet == .)) %>%
    map(~ pull(., weight)) %>%
    map(~ jarque.bera.test(.))