2011-05-31 21 views
8

Biểu thức R chuẩn outer(X, Y, f) đánh giá ma trận có mục nhập (i, j) -th có giá trị f(X[i], Y[j]).Làm cách nào để khái quát hóa kích thước bên ngoài với n?

Tôi muốn thực hiện chức năng multi.outer, tổng quát n-chiều outer: multi.outer(f, X_1, ..., X_n), trong đó f là một số hàm n-ary, sẽ tạo ra (chiều dài (X_1) * ... * chiều dài (X_n)) mảng có (i_1, ..., i_n) -th entry có giá trị f(X_1[i_1], ..., X_n[i_n]) cho tất cả các bộ chỉ mục hợp lệ (i_1, ..., i_n). Rõ ràng, đối với mỗi i trong {1, ..., n}, tất cả các phần tử của X_i trong multi.outer(f, X_1,...,X_i,..., X_n) phải là đối số thứ i cho phép đối với hàm f. Đối với trường hợp n = 2, multi.outer sẽ thực hiện tương tự như outer, mặc dù nó có chữ ký khác (IOW, multi.outer(f, X, Y) sẽ tương đương với outer(X, Y, f)). Điều quan trọng cần lưu ý là, mặc dù các đối số X_1, ..., X_n của multi.outer là tất cả các vec-tơ, chúng không nhất thiết phải có cùng một chế độ. Ví dụ. X_1 và X_2 có thể là c(1, 2, 3)LETTERS[10:20], tương ứng.

Cảm ơn!

Trả lời

16

Đây là một cách: Đầu tiên sử dụng Vectorizeouter để xác định một chức năng mà tạo ra một ma trận n-chiều nơi mỗi mục là một danh sách các đối số mà hàm được sẽ được áp dụng:

list_args <- Vectorize(function(a,b) c(as.list(a), as.list(b)), 
         SIMPLIFY = FALSE) 


make_args_mtx <- function(alist) { 
    Reduce(function(x, y) outer(x, y, list_args), alist) 
} 

Bây giờ multi.outer chỉ cần gọi applydo.call về vấn đề này "args-ma trận":

0.123.
multi.outer <- function(f, ...) { 
    args <- make_args_mtx(list(...)) 
    apply(args, 1:length(dim(args)), function(a) do.call(f, a[[1]])) 
} 

Hãy thử điều này với một chức năng ví dụ:

fun <- function(a,b,c) paste(a,b,c) 

ans <- multi.outer(fun, LETTERS[1:2], c(3, 4, 5), letters[6:7]) 

> ans 
, , 1 

    [,1] [,2] [,3] 
[1,] "A 3 f" "A 4 f" "A 5 f" 
[2,] "B 3 f" "B 4 f" "B 5 f" 

, , 2 

    [,1] [,2] [,3] 
[1,] "A 3 g" "A 4 g" "A 5 g" 
[2,] "B 3 g" "B 4 g" "B 5 g" 
+0

Đẹp! Xem câu hỏi tương tự (nhưng không phức tạp) với câu trả lời tương tự ở đây: http: // stackoverflow.com/questions/5233308/is-there-a-r-function-that-apply-a-chức năng-cho-mỗi-cặp-cột/5233713 # 5233713 – Aaron

1

Làm thế nào về điều này:


multi.outer<-function(f,...){ 

    apply(expand.grid(...),1,function(x){do.call(f,as.list(x))}) 

} 
+0

Tôi tin rằng OP muốn kết quả nằm trong ma trận n chiều, với mỗi thứ nguyên tương ứng với mỗi đối số của 'f'. –

+0

+1 để làm cho tôi biết về 'expand.grid', nhưng khi tôi thử' multi.outer' này (lần đầu tiên) với hàm test 'function (s, b, l) {substr (s, b, b + l - 1)} ', và' c ("ABCDEFGH", "IJKLMNOP", "QRSTUVWX"), 1: 5, 2: 3' như phần còn lại của các đối số, tôi nhận được 'Lỗi trong hàm (s, b, l): đối số không được sử dụng (Var1 = "ABCDEFGH", Var2 = "1", Var3 = "2") '. Tôi đã không có cơ hội để tìm ra những gì triển khai của bạn, hoặc tại sao lỗi này. – kjo

0

Tôi nghĩ rằng chúng ta có thể làm điều này bằng Vectorize Outer và.

sigm = function(a=0,b=0,x){ 
return(exp(x*a+b)) 
} 

sigm1 = Vectorize(function(a=-1:1,b=-1:1,x){ 

outer(a,b,sigm,x) 
},SIMPLIFY = FALSE) 

Bây giờ, sigm1 (x = 1: 3) cho sản lượng yêu cầu

[[1]] 
     [,1]  [,2]  [,3] 
[1,] 0.1353353 0.3678794 1.000000 
[2,] 0.3678794 1.0000000 2.718282 
[3,] 1.0000000 2.7182818 7.389056 

[[2]] 
     [,1]  [,2]  [,3] 
[1,] 0.04978707 0.1353353 0.3678794 
[2,] 0.36787944 1.0000000 2.7182818 
[3,] 2.71828183 7.3890561 20.0855369 

[[3]] 
     [,1]  [,2]  [,3] 
[1,] 0.01831564 0.04978707 0.1353353 
[2,] 0.36787944 1.00000000 2.7182818 
[3,] 7.38905610 20.08553692 54.5981500 

Các chỉ vẽ trở lại với đoạn mã này được Tôi đang sử dụng các giá trị mặc định của a = -1: 1 và b = -1: 1. Khi tôi cố gắng để vượt qua cùng trong khi gọi điện thoại, nó đi haywire. Ví dụ.

sigm1(-1:1,-1:1,1:3) 

[[1]] 
     [,1] 
[1,] 0.1353353 

[[2]] 
[,1] 
[1,] 1 

[[3]] 
    [,1] 
[1,] 54.59815 

Tôi không thể tìm ra lý do vượt qua các đối số là tạo sự khác biệt về đầu ra.

Các vấn đề liên quan