Перебор декартовых произведений векторов

у меня есть следующий вложенный цикл:

for (x in xs) {
    for (y in ys) {
        # Do something with x and y
    }
}

который я хотел бы сгладить, поэтому я подумал о создании Декартового произведения двух векторов xs и ys и повторение результата. В Python, это было бы тривиально:

for xy in product(xs, ys):
    # x, y = xy[0], xy[1]

но в R самый простой эквивалент, который я нашел, выглядит устрашающим:

xys <- expand.grid(xs, ys)
for (i in 1 : nrow(xys)) {
    xy <- as.vector(xys[i, ])
    # x <- xy[1], y <- xy[2]
}

конечно, должен быть лучший способ, нет? (Чтобы уточнить, я не хочу повторять индекс ... Я думаю, что должен быть способ прямого перебора кортежей в продукте.)

2 ответов


можно использовать apply функция для применения функции к каждой строке фрейма данных. Просто замените "your function" С вашей фактической функции.

# example data
xs <- rnorm(10)
ys <- rnorm(10)    

apply(expand.grid(xs, ys), 1, FUN = function(x) {"your function"})

это очень простой пример. Здесь вычисляется сумма обоих значений в строке:

apply(expand.grid(xs, ys), 1, FUN = function(x) {x[1] + x[2]})

вот вариант, который использует именованные аргументы (xs, ys) вместо индексов (x[1], x[2]):

myfun <- function(xs, ys) xs + ys
arguments <- expand.grid(xs = rnorm(10), ys = rnorm(10))
apply(arguments, 1, function(x)do.call(myfun, as.list(x)))

R имеет другую парадигму, чем Python, поэтому не ожидайте, что у него будут генераторы или кортежи-у нас есть векторы и индексы для этого.

таким образом, чтобы отобразить функцию на декартовом произведении, просто вызовите

outer(xs,ys,function(x,y) ...)

и undim результат, если вы хотите.

EDIT: в случае xs или ys являются чем-то более сложным, чем базовые векторы, один из вариантов-использовать индексы, т. е.

outer(seq(a=xs),seq(a=ys),function(xi,yi) ... xs[[xi]]/ys[xi,]/etc. ...)

или сопоставьте функцию на продукте ручной работы бита используя mapply

mapply(function(x,y) ...,xs,rep(ys,each=length(xs)))