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