使用 map 进行参数值迭代

iteration using map for parameter values

假设我有一个简单的功率分析:

> power.t.test(power = .90, delta = 1)

我想对来自具有幂和增量值的两个向量的值的所有排列使用此函数:

> power_vector <- c(0.85, 0.90, 0.95)
> delta_vector <- c(0.5, 1, 1.5)

这样第一个函数将使用 0.85 的幂和 0.5 的增量,第二个函数将使用 0.85 的幂和 1 的增量,...直到用尽所有排列。

这可以用 purrr:map()purrr:map2() 完成吗?

对组合使用 expand.grid 并传递给 pmap,因为 map 会引发错误:

df_map <- expand.grid(power=power_vector, delta=delta_vector)
purrr::pmap(df_map, power.t.test)

因为这会生成一个列表,您可能只需要一个向量:

sapply( purrr::pmap(df_map, power.t.test), "[[", "n")
[1]  72.800532  85.031289 104.927952  18.968545  22.021098  26.989219   9.053694  10.401465
[9]  12.598722

> cbind( df_map, n=sapply( purrr::pmap(df_map, power.t.test), "[[", "n") )
  power delta          n
1  0.85   0.5  72.800532
2  0.90   0.5  85.031289
3  0.95   0.5 104.927952
4  0.85   1.0  18.968545
5  0.90   1.0  22.021098
6  0.95   1.0  26.989219
7  0.85   1.5   9.053694
8  0.90   1.5  10.401465
9  0.95   1.5  12.598722

您可以使用 purrr::cross2 进行交叉(笛卡尔)连接以获得单个列表中的组合,然后使用 map:

进行迭代
library(purrr)

power_vector <- c(0.85, 0.90, 0.95)
delta_vector <- c(0.5, 1, 1.5)

tests1 <- cross2(power_vector, delta_vector) %>% 
    map(~power.t.test(power = .x[[1]], delta = .x[[2]]))

tests1[[1]]
#> 
#>      Two-sample t test power calculation 
#> 
#>               n = 72.80053
#>           delta = 0.5
#>              sd = 1
#>       sig.level = 0.05
#>           power = 0.85
#>     alternative = two.sided
#> 
#> NOTE: n is number in *each* group

另一种方法是制作一个命名的向量列表,对其调用 cross,然后对结果进行迭代 lift(power.t.test),其中 lift 修改函数以采用作为输入的参数列表(向后 do.callpurrr::invoke,如果你愿意的话):

tests3 <- list(power = power_vector, 
               delta = delta_vector) %>% 
    cross() %>% 
    map(lift(power.t.test))

tests3[[3]]
#> 
#>      Two-sample t test power calculation 
#> 
#>               n = 104.928
#>           delta = 0.5
#>              sd = 1
#>       sig.level = 0.05
#>           power = 0.95
#>     alternative = two.sided
#> 
#> NOTE: n is number in *each* group

在基础 R 中,

tests2 <- do.call(Map, 
                  c(power.t.test, 
                    expand.grid(power = power_vector, 
                                delta = delta_vector)))

tests2[[2]]
#> 
#>      Two-sample t test power calculation 
#> 
#>               n = 85.03129
#>           delta = 0.5
#>              sd = 1
#>       sig.level = 0.05
#>           power = 0.9
#>     alternative = two.sided
#> 
#> NOTE: n is number in *each* group