2012-09-09 15 views
6

Mam następujący zagnieżdżona pętla:iteracyjnego iloczyn kartezjański wektorów

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

Które chciałbym spłaszczyć tak myślałem budowy iloczyn kartezjański dwóch wektorów xs i ys i iteracji nad wyniku . W Pythonie, byłoby to banalne:

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

Ale w R, najprostszy równoważne Znalazłem wygląda trudne:

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

pewnością nie musi być lepszy sposób, nie? (Dla wyjaśnienia, nie chcę iteracyjne nad indeks ... myślę, że musi być jakiś sposób, aby bezpośrednio iteracyjne nad krotek w produkcie.)

Odpowiedz

8

można użyć funkcji apply zastosować funkcję do każdego wiersza ramki danych. Wystarczy zastąpić "your function" swoją rzeczywistą funkcją.

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

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

To bardzo prosty przykład. Tutaj, suma obu wartości w wierszu jest obliczana:

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

tutaj jest wariant, który używa nazwanych argumentów (xs, ys) zamiast indeksów (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: Usunąłem odpowiedź. Nie było w tym nic złego. Nie byłem pewien, czy było to dokładnie rozwiązanie, którego szukałeś. @flodel ma rację co do problemów przy użyciu 'apply' z mieszanym typem danych wejściowych. W takim przypadku możesz użyć 'as.numeric', aby przekształcić ciąg znaków w wartość liczbową. Ale nie ma problemu, o ile używasz tylko wektorów liczbowych. –

10

R ma inny paradygmat niż Python, więc don” t oczekiwać, że będzie mieć generatory lub krotki - mamy wektory i wskaźniki dla tego.

ten sposób mapować funkcję na iloczyn kartezjański po prostu zadzwonić

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

i undim wynik, jeśli chcesz.

EDIT: W przypadku xs lub ys są czymś bardziej skomplikowane niż wektorów bazowych, jedną z opcji jest wykorzystanie wskaźników, tj

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

lub zmapować funkcji na kawałku produktu ręcznie wykonane przy użyciu mapply

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

nie jestem zainteresowana z różnych paradygmatów. Jestem * zaniepokojony przenikliwością zmiennych indeksowych w moim kodzie. O ile rozumiem R, większość/wszystkie z nich powinny być niepotrzebne. Twój przykładowy kod * * wygląda jak co Rozglądałem przez to zachowuje się w niewłaściwy sposób: 'zewnętrzna (1: 2, 3: 4, funkcja (x, y) {print (sprintf ('% d,% d' x, y))} '- to drukuje tablicę * i * macierz z wynikami - tak ja nie wiem jak do przerobienia mojego pętli tu pracować ... (nie wiem co masz na myśli przez„undim” może to byłoby to wyjaśnić). –

+0

UUH, poprzedni komentarz jest głupie. matryca jest tylko wartość zwracana 'outer'. niemniej jednak, nadal nie jestem pewien, w jaki sposób dostosować to do pracy jako zamiennik mojego zagnieżdżonej pętli od '' y' x' i są wektory, a nie skalary. Niestety, ja naprawdę potrzebuję skalary. –

+0

@KonradRudolph Ok, przedłużony. – mbq

Powiązane problemy