Перебор декартовых произведений векторов
у меня есть следующий вложенный цикл:
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)))