2012-09-09 32 views
6

tôi đã vòng lặp lồng nhau sau:lặp trên sản phẩm Cartesian của vectơ

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

Mà tôi muốn flatten vì vậy tôi nghĩ đến việc xây dựng một sản phẩm Descartes của hai vectơ xsys và lặp lại qua kết quả . Trong Python, đây sẽ là tầm thường:

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

Nhưng trong R, tương đương đơn giản nhất tôi đã tìm thấy trông khó khăn:

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

Chắc chắn phải có một cách tốt hơn, đúng không? (Để làm rõ, tôi không muốn lặp qua một chỉ số ... Tôi nghĩ rằng phải có cách để trực tiếp lặp qua các bộ dữ liệu trong sản phẩm.)

Trả lời

8

Bạn có thể sử dụng chức năng apply để áp dụng một chức năng cho mỗi hàng trong khung dữ liệu của bạn. Chỉ cần thay thế "your function" bằng chức năng thực tế của bạn.

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

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

Đây là ví dụ rất cơ bản. Ở đây, tổng của cả hai giá trị liên tiếp được tính:

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

đây là một biến thể sử dụng đối số tên (xs, ys) thay vì chỉ số (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))) 
+0

@Konrad Rudolph: Tôi đã bỏ lại câu trả lời của tôi. Không có gì sai với nó. Tôi không chắc đó có phải là giải pháp mà bạn tìm kiếm hay không. @flodel đúng về các vấn đề khi sử dụng 'apply' với các kiểu đầu vào hỗn hợp. Trong trường hợp này, bạn có thể sử dụng 'as.numeric' để chuyển đổi một chuỗi thành một giá trị số. Nhưng không có vấn đề gì miễn là bạn chỉ sử dụng các vectơ số. –

10

R có một mô hình khác với Python, vì vậy đừng ' Tôi hy vọng nó có máy phát điện hoặc bộ tuples - chúng tôi có vectơ và chỉ số cho điều đó.

Bằng cách này, để ánh xạ một chức năng trên một sản phẩm Descartes chỉ cần gọi

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

và undim kết quả nếu bạn muốn.

EDIT: Trong trường hợp xs hoặc ys là một cái gì đó phức tạp hơn vectơ cơ sở, một lựa chọn là sử dụng các chỉ số, tức là

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

hoặc bản đồ một chức năng trên một sản phẩm hand-crafted chút bằng mapply

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

Tôi không quan tâm đến các mô hình khác nhau. I * am * lo ngại về tính phổ biến của các biến chỉ mục trong mã của tôi. Theo như tôi hiểu R, hầu hết/tất cả chúng đều không cần thiết. Mã ví dụ của bạn * trông * giống như những gì tôi đã tìm kiếm nó hoạt động theo cách sai: 'bên ngoài (1: 2, 3: 4, hàm (x, y) {print (sprintf ('% d,% d', x, y))} '- điều này in một mảng * và * một ma trận với kết quả - vì vậy tôi không biết cách viết lại vòng lặp của mình để làm việc ở đây ... (Tôi không biết ý bạn là gì bởi" undim ", Có lẽ điều này sẽ giải thích nó.) –

+0

Uuh, bình luận trước đó là ngu ngốc. Ma trận chỉ là giá trị trả về của 'bên ngoài' .Tuy nhiên, tôi vẫn không chắc chắn làm thế nào để điều chỉnh này để làm việc như là một thay thế vòng lặp lồng nhau của tôi, vì 'x' và' y' là các vectơ chứ không phải là vô hướng. Thật không may, tôi thực sự cần có vô hướng –

+0

@KonradRudolph Ok, mở rộng – mbq

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