2016-03-09 2 views
3

Рассмотрим эту функцию игрушку, которая принимает 3 аргумента:mapply для комбинаций всех аргументов [R]

toy <- function(x, y, z){ 
    paste(x, y, z) 
} 

Для каждого аргумента у меня есть несколько значений (не обязательно один и тот же номер для каждого аргумента), и я хочу применить функцию toy к различным комбинациям этих аргументов.

Итак, я подумал, хорошо, давайте использовать многомерную версию применяемых функций mapply.

mapply(FUN = toy, x = 1:2, y = c("#", "$"), z = c("a", "b")) 

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

Но это не совсем то, что я хотел. Действительно, согласно справке mapply "применяется FUN к первым элементам каждого ... аргумента, второму элементу, третьим элементам и т. Д.". И я хочу применить FUN ко всем различным комбинациям всех аргументов.

Таким образом, вместо

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

В результате я хотел бы скорее:

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

Итак, мой вопрос, что это умный способ сделать это?

Конечно, я могу заранее подготовить комбинации и упорядочить аргументы для mapply, чтобы они включали в себя - все комбинации. Но я просто подумал, что это может быть довольно распространенной задачей, и в рамках семейства приложений может быть уже функция, которая может это сделать.

+1

Вы можете сделать 'do.call (вставить, expand.grid (x = 1: 2, y = c (" # "," $ "), z = c (" a "," b ")))) 'возможно –

ответ

4

Вы могли бы объединить do.call с expand.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), например, для проверки.

+0

благодаря' expand.grid' работает для подготовки комбинаций. Я просто должен был сделать это в два этапа. Во-первых, 'args <- expand.grid (x = 1: 2, y = c (" # "," $ "), z = c (" a "," b "))' then '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.call' и' paste' для этой конкретной игрушечной функции. Моя фактическая функция отличается от . – elikesprogramming

+0

Хорошо, но 'do.call' векторизован и намного эффективнее, чем' mapply', но, возможно, он не всегда может быть израсходован на более общие случаи. –

Смежные вопросы