2015-05-15 9 views
7

Próbuję uniknąć używania pętli, używając apply do zastosowania funkcji zdefiniowanej przez użytkownika do macierzy. Problem polega na tym, że istnieją dodatkowe parametry, których używa moja funkcja i które różnią się dla każdej kolumny macierzy. Poniżej znajduje się przykład zabawki.Używanie "apply" do zastosowania funkcji do macierzy, w której parametry są specyficzne dla kolumny

że mam następującą funkcję:

foo <- function(x, a, b, c) return((a*x + b)^c) 

i chcę, aby zastosować go do matrycy bar używając różnych wartości a, b i c dla każdej kolumny.

bar <- matrix(1:15, ncol = 3) 
a <- 4:6 
b <- 3:1 
c <- 1:3 

W tym przypadku, w pierwszej kolumnie, po czym a=4bar, b=3 i c=1. Próbowałem tego, ale jest to oczywiście niepoprawne, ponieważ każda kolumna używa kolejno wszystkich parametrów przed zawinięciem do pierwszego parametru ponownie. Jakieś sugestie?

Odpowiedz

12

Mogliśmy split „Pasek” w kolumnie „” (col(bar)) i mapply można zastosować „foo” do odpowiadającej „a”, „b”, wartości „C” do każdej kolumny „bar”

mapply(foo, split(bar, col(bar)), a, b, c) 

Albo bez użycia apply

ind <- col(bar) 
(a[ind]*bar +b[ind])^c[ind] 
+2

Zamiast 'split' możesz użyć również' as.data.frame'. – nicola

+0

@nicola Tak, myślałem, aby zachować go w 'macierzy' – akrun

+2

Już wcześniej awansowałem, a teraz chciałbym mieć możliwość dodawania głosów za wyjątkowo elegancką edycję. –

2

można umieścić swoje parametry do wektora:

newbar <- rbind(a,b,c,bar) 
newfoo <- function(z){x <- z[-(1:3)]; (z[1]*x+z[2])^z[3]} 
apply(newbar,2,newfoo) 

co daje

[,1] [,2] [,3] 
    7 1024 300763 
    11 1369 389017 
    15 1764 493039 
    19 2209 614125 
    23 2704 753571 
2

Można użyć sweep; zwykle jest to dla odjęcie średniej z każdej kolumny, ale można przejść w indeksie zamiast dostać indeksowanie równoległego poprzek a, b i c:

> sweep(bar, 2, seq_along(a), function(x,i) foo(x, a[i], b[i], c[i]), FALSE) 
    [,1] [,2] [,3] 
[1,] 7 1024 300763 
[2,] 11 1369 389017 
[3,] 15 1764 493039 
[4,] 19 2209 614125 
[5,] 23 2704 753571 
+0

Zobacz także http://stackoverflow.com/questions/3444889/how-to-use-the-r-function-sweep –

9

nie widzę dlaczego męczyć się z funkcji w ogóle :

> a <- matrix(4:6,nrow = 5,ncol = 3,byrow = TRUE) 
> b <- matrix(3:1,nrow = 5,ncol = 3,byrow = TRUE) 
> c <- matrix(1:3,nrow = 5,ncol = 3,byrow = TRUE) 
> (a*bar + b)^c 
    [,1] [,2] [,3] 
[1,] 7 1024 300763 
[2,] 11 1369 389017 
[3,] 15 1764 493039 
[4,] 19 2209 614125 
[5,] 23 2704 753571 
+0

To jest bardziej eleganckie, chociaż powinienem je przetestować .. – akrun

+0

@akrun Ah, tęskniłem za koniec twojej odpowiedzi. – joran

+0

Jest w porządku. I tak bym tego nie odgadł. – akrun

3

myślę, że można po prostu przenieść swój matrycy i używać wektoryzacji:

t(foo(t(bar),a,b,c)) 

to powinno działać na każdym wektorowy foo.