首页 > 解决方案 > 是否有一个函数可以为多个变量运行所有可能的值组合?

问题描述

如果我错过了执行此操作的现有功能,但很难找到一些东西,我深表歉意。

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

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

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

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

谢谢。

标签: r

解决方案


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

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

expand.gridis的替代方法,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(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.vectorgen.vector.char不是使用引号或大括号。

3c) 理解

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

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

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")

推荐阅读