为所有参数组合使用mapply [R]

8
考虑一下以下这个接收3个参数的玩具函数:
toy <- function(x, y, z){
    paste(x, y, z)
}

对于每个参数,我都有一些值(不一定是每个参数都有相同数量的值),我想将toy函数应用于这些参数的不同组合。因此,我想到可以使用apply函数的多元版本mapply
mapply(FUN = toy, x = 1:2, y = c("#", "$"), z = c("a", "b"))

[1] "1 # a" "2 $ b"

但这并不是我想要的。实际上,根据 mapply 的帮助文档,“将FUN应用于每个...参数的第一个元素、第二个元素、第三个元素等等”。我想要的是将FUN应用于所有参数的不同组合。
因此,我们可以使用expand.grid()函数来获取所有参数的不同组合,并使用mapply()函数将FUN应用于每个组合。
[1] "1 # a" "2 $ b"

The result I would like is rather:

[1] "1 # a" "1 # b" "1 $ a" "1 $ b" "2 # a" "2 # b" "2 $ a" "2 $ b"

所以,我的问题是有什么聪明的方法可以做到这一点?
当然,我可以事先准备好组合,并安排参数供 -rowwise- 包括所有组合。但我认为这可能是一个相当常见的任务,可能已经有一个函数,在 apply-family 中可以完成这个任务。

1
也许你可以使用 do.call(paste, expand.grid(x = 1:2, y = c("#", "$"), z = c("a", "b"))) - David Arenburg
1个回答

11

您可以结合do.callexpand.grid使用以下方式处理无限数量的输入:

toy <- function(...) do.call(paste, expand.grid(...))

那么,你可以这样做

x = 1:2 ; y = c("#", "$") ; z = c("a", "b")
toy(x, y, z)
# [1] "1 # a" "2 # a" "1 $ a" "2 $ a" "1 # b" "2 # b" "1 $ b" "2 $ b"

这将适用于任何输入。 您可以尝试像toy(x, y, z, y, y, y, z)这样的内容,以验证其有效性。


4
谢谢,expand.grid函数很好地完成了组合的准备工作。我只需要分两步来完成它。首先,使用args <- expand.grid(x = 1:2, y = c("#", "$"), z = c("a", "b"))进行组合设置,然后使用mapply(FUN = toy, x = args$x, y = args$y, z = args$z)调用函数,因为直接这样做mapply(FUN = toy, expand.grid(x = 1:2, y = c("#", "$"), z = c("a", "b")))不会起作用(mapply将仅接收一个参数;即data.frame)。 我曾经认为有些函数可以在内部完成这种操作。对于这个特定的玩具函数,我使用了do.callpaste。我的实际函数是不同的。 - elikesprogramming
虽然do.call是矢量化的,并且比mapply更高效,但可能并不总是适用于更一般的情况。 - David Arenburg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接