Есть ли какая-нибудь функция перекрестного применения в R?

#r

#r

Вопрос:

Есть ли какая-то функция в R в виде:

 crossApply(v1, v2, func)
  

это имеет ту же функциональность, что и:

 ret = c()
i = 1
for (e1 in v1) {
  for (e2 in v2) {
    ret[i] <- func(e1,e2)
    i <- i   1
  }
}
return(ret)
  

Заранее спасибо.

Ответ №1:

Я думаю, вы можете искать outer , что не совсем то, что делает ваш код, но это близко. В частности, outer Вернет матрицу (т. Е. Внешнее произведение) или каждую комбинацию элементов ее первых двух аргументов.

Вероятно, вы захотите сохранить результат, а затем извлечь нижний треугольник в виде вектора. Может быть, что-то вроде этого:

 rs <- outer(1:4,-(5:7)," ")
rs[lower.tri(rs,diag = TRUE)]
[1] -4 -3 -2 -1 -4 -3 -2 -4 -3
  

Комментарии:

1. Спасибо! Как я могу определить пользовательскую функцию для использования во внешнем? Не могли бы вы привести пример? Я продолжаю получать ошибки при попытке этого, и мои сообщения об ошибках на китайском языке, поэтому, я думаю, их публикация мало поможет.

2. @SpiritZhang: emulatesum<-function(x,y) return(x y) как функция, а затем rs <- outer(1:4,-(5:7),"emulatesum") . Кстати: я настоятельно рекомендую использовать R на английском языке, особенно для сообщений об ошибках: их поиск в Google намного проще, когда они у вас есть на английском…

3. @NickSabbe: Спасибо, Ник! Я не обращал особого внимания на язык, когда устанавливал R. Поскольку я в Китае, я думаю, именно поэтому R сделал китайский язык языком по умолчанию.

Ответ №2:

Пример

 func <- function(x,y) {sqrt(x^2 y^2)}
v1 <- c(1,3,5)
v2 <- c(0,-4,-12)
ret <- outer(v1,v2,"func")
  

И тогда у вас есть

 > ret
     [,1]     [,2]     [,3]
[1,]    1 4.123106 12.04159
[2,]    3 5.000000 12.36932
[3,]    5 6.403124 13.00000
  

или, если вы хотите, чтобы именно то, что создавали ваши циклы for

 > as.vector(t(ret))
[1]  1.000000  4.123106 12.041595  3.000000  5.000000 12.369317  5.000000
[8]  6.403124 13.000000
  

Ответ №3:

Это довольно легко сделать с do.call помощью и expand.grid :

 x <- seq(0,10, length.out=10)
> y <- seq(-1,1, length.out=5)
> d1 <- expand.grid(x=x, y=y)  
> do.call("*", d1)
 [1]   0.0000000  -1.1111111  -2.2222222  -3.3333333  -4.4444444
 [6]  -5.5555556  -6.6666667  -7.7777778  -8.8888889 -10.0000000
[11]   0.0000000  -0.5555556  -1.1111111  -1.6666667  -2.2222222
[16]  -2.7777778  -3.3333333  -3.8888889  -4.4444444  -5.0000000
[21]   0.0000000   0.0000000   0.0000000   0.0000000   0.0000000
[26]   0.0000000   0.0000000   0.0000000   0.0000000   0.0000000
[31]   0.0000000   0.5555556   1.1111111   1.6666667   2.2222222
[36]   2.7777778   3.3333333   3.8888889   4.4444444   5.0000000
[41]   0.0000000   1.1111111   2.2222222   3.3333333   4.4444444
[46]   5.5555556   6.6666667   7.7777778   8.8888889  10.0000000
  

Комментарии:

1. Отлично, но обратите внимание, что do.call в этом случае может работать только векторизованная функция. например, do.call(означает, d1) завершается с ошибкой.

2. так что, возможно, так и должно быть do.call("mapply", c(fun, d1)) .

3. Интересная идея. Кажется, это связано с do.call(expand.grid(.)) тем, что Vectorize делает с. sapply