【问题标题】:Is there a function to run all possible combinations of values for multiple variables?是否有一个函数可以为多个变量运行所有可能的值组合?
【发布时间】:2021-01-24 12:38:08
【问题描述】:

抱歉,如果我错过了执行此操作的现有功能,但正在努力寻找某些东西。

基本上我有一个如下示例(保持通用):

function <- (var1, var2)
values_for_var1 <- c("a", "b", "c")
values_for_var2 <- c(1:5)

我想知道是否有一个快速函数可以让我“输入”分别列在var1var2 的两个向量,并针对所有可能的配对运行它?例如,运行函数 where var1 == "a" for var2 == 1,然后是 var2 == 2,然后是 var2 == 3,等等,然后重复 var1 == "b"var2 == c

可以进行“长期”循环,但是对于许多变量或所述变量的可能值,这不能很好地扩展。我认为purrr 可能有一些东西,但除非我误读了指南,否则它不会这样做。

谢谢。

【问题讨论】:

    标签: r


    【解决方案1】:

    1) expand.grid expand.grid 将在网格数据框g 中给出其参数的所有组合。然后我们就可以对g的行进行操作了。

    请注意,expand.grid 将默认将字符输入转换为因子,除非将 stringsAsFactors = FALSE 指定为其参数。

    expand.grid 的替代方法是 merge,但它仅限于两个参数,而 expand.grid 可以使用任何数字。

    # inputs
    var1 <- letters[1:3]
    var2 <- 1:5
    f <- function(let, num) paste(10 * num, let)
    
    # create grid
    g <- expand.grid(var1, var2)
    
    # operate on each row of grid
    
    do.call(mapply, c("f", unname(as.list(g))))
    # or
    sapply(1:nrow(g), function(i) do.call("f", unname(g[i, ])))
    # or
    mapply(f, g[, 1], g[, 2])
    

    这些也适用于(或者可以在最后一个的情况下进行调整)用于具有相同数量参数的函数的超过 2 个向量。

    2) 外部 对于只有 2 个变量(正如我们在这里),另一种方法是使用外部。这会产生一个 length(var1) by length(var2) 矩阵。请注意,outer 仅适用于矢量化函数,因此通常这样编写:

    outer(var1, var2, Vectorize(f))
    

    3) 理解

    CRAN 上有三个包支持类似 Python 的理解,可能会修改语法。

    3a) 电子列表

    library(eList)
    Chr(for(v1 in var1) for(v2 in var2) f(v1, v2))
    

    如果结果是数字,则使用 Num 代替 Chr,或者如果结果是复杂对象,则使用 List。

    3b) 列表计算

    library(listcompr)
    
    n1 <- length(var1); n2 <- length(var2)
    gen.vector.char("{ f(var1[i], var2[j]) }", i = 1:n1, j = 1:n2)
    

    如果结果是数字,请使用 gen.vector 而不是 gen.vector.char,并且不要使用引号或大括号。

    3c) 理解

    library(comprehenr)
    to_vec(for (v1 in var1) for(v2 in var2) f(v1, v2))
    

    4) 其他 一些包有 expand.grid 的替代品,然后我们可以使用该包的功能来应用 f 或本地复制它。

    4a) dplyr/tidyr

    library(dplyr)
    library(tidyr)
    crossing(var1, var2) %>%
      rowwise %>%
      mutate(result = f(var1, var2)) %>%
      ungroup
    

    4b) 数据表

    library(data.table)
    outDT <- CJ(var1, var2)[, result := f(var1, var2), by = .I]
    

    4c) sqldf

    library(sqldf)
    var1df <- data.frame(var1); var2df <- data.frame(var2)
    sqldf("select (10 * var2) || ' ' || var1 from var1df, var2df")
    

    【讨论】:

      【解决方案2】:

      也许你可以像下面这样expand.grid + Vectorize

      with(
        expand.grid(values_for_var1, values_for_var2),
        Vectorize(func)(Var1, Var2)
      )
      

      【讨论】:

        猜你喜欢
        • 2020-12-30
        • 1970-01-01
        • 1970-01-01
        • 2015-05-13
        • 1970-01-01
        • 2012-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多