2011-11-23 8 views
6

Mam następujące ramki danych i wektorowe.Jak zastosować funkcję wielu parametrów w R?

> y 
    v1 v2 v3 
1 1 6 43 
2 4 7 5 
3 0 2 32 

> v 
[1] 1 2 3 

Chcę zastosować następującą funkcję do każdego ROW w tej ramce danych, takie, że v jest dodawany do każdego ROW z Y:

x <- function(vector1,vector2) { 
    x <- vector1 + vector2 
} 

... w celu uzyskania wyniki:

v1 v2 v3 
1 2 8 46 
2 5 9 8 
3 1 4 35 

mapply stosuje funkcję KOLUMN:

> z <- mapply(x, y, MoreArgs=list(vector2=v)) 
> z 
    v1 v2 v3 
[1,] 2 7 44 
[2,] 6 9 7 
[3,] 3 5 35 

Próbowałem transpozycji ramki danych tak, że funkcja zostanie zastosowana do wierszy i kolumn nie, ale mapply daje mi dziwne wyniki po transpozycji:

> transposed <- t(y) 
> transposed 
    [,1] [,2] [,3] 
v1 1 4 0 
v2 6 7 2 
v3 43 5 32 

> z <- mapply(x, transposed, MoreArgs=list(vector2=v)) 
> z 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 2 7 44 5 8 6 1 3 33 
[2,] 3 8 45 6 9 7 2 4 34 
[3,] 4 9 46 7 10 8 3 5 35 

... Pomoc?

####################### EDYCJA ################# ########

Dzięki za wszystkie odpowiedzi! Uczę się ton nowych funkcji R, których nigdy wcześniej nie widziałem, co jest fantastyczne.

Chciałbym wyjaśnić nieco moje wcześniejsze pytanie. To, o co naprawdę zadaję, to o wiele bardziej ogólne pytanie - jak zastosować funkcję wieloparametrową do każdego rzędu w R (w tej chwili mam ochotę dojść do wniosku, że powinienem użyć pętli, ale chciałbym dowiedzieć się, czy jest to możliwe, tylko dla przyszłego odniesienia ...) (Ja również celowo powstrzymałem się od pokazywania kodu, z którym pracuję, ponieważ jest to trochę nieporządne).

Próbowałem przy użyciu funkcji przeciągnięcia jak sugerowano, ale pojawia się następujący błąd:

testsweep <- function(vector, z, n) { 
    testsweep <- z 
} 
> n <- names(Na_exp) 
> n 
[1] "NaCl.10000.2hr.AVG_Signal" "NaCl.10000.4hr.AVG_Signal" 


> t <- head(Li_fcs,n=1) 
> t 
    LiCl.1000.1hr.FoldChange LiCl.2000.1hr.FoldChange LiCl.5000.1hr.FoldChange 
[1,]    -0.05371838    -0.1010928    -0.01939986 
    LiCl.10000.1hr.FoldChange LiCl.1000.2hr.FoldChange 
[1,]     0.1275617    -0.107154 
    LiCl.2000.2hr.FoldChange LiCl.5000.2hr.FoldChange 
[1,]    -0.06760782    -0.09770226 
    LiCl.10000.2hr.FoldChange LiCl.1000.4hr.FoldChange 
[1,]    -0.1124188    -0.06140386 
    LiCl.2000.4hr.FoldChange LiCl.5000.4hr.FoldChange 
[1,]    -0.04323497    -0.04275953 
    LiCl.10000.4hr.FoldChange LiCl.1000.8hr.FoldChange 
[1,]    0.03633496    0.01879461 
    LiCl.2000.8hr.FoldChange LiCl.5000.8hr.FoldChange 
[1,]     0.257977    -0.06357423 
    LiCl.10000.8hr.FoldChange 
[1,]    0.07214176 


> z <- colnames(Li_fcs) 
> z 
[1] "LiCl.1000.1hr.FoldChange" "LiCl.2000.1hr.FoldChange" 
[3] "LiCl.5000.1hr.FoldChange" "LiCl.10000.1hr.FoldChange" 
[5] "LiCl.1000.2hr.FoldChange" "LiCl.2000.2hr.FoldChange" 
[7] "LiCl.5000.2hr.FoldChange" "LiCl.10000.2hr.FoldChange" 
[9] "LiCl.1000.4hr.FoldChange" "LiCl.2000.4hr.FoldChange" 
[11] "LiCl.5000.4hr.FoldChange" "LiCl.10000.4hr.FoldChange" 
[13] "LiCl.1000.8hr.FoldChange" "LiCl.2000.8hr.FoldChange" 
[15] "LiCl.5000.8hr.FoldChange" "LiCl.10000.8hr.FoldChange" 

Ale gdy próbuję zastosować zamiatać ...

> test <- sweep(t, 2, z, n, FUN="testsweep") 
Error in if (check.margin) { : argument is not interpretable as logical 
In addition: Warning message: 
In if (check.margin) { : 
    the condition has length > 1 and only the first element will be used 

Kiedy usunąć n parametr z tego przykładu testu, zamiatanie działa dobrze. Sugeruje mi to, że przeciągnięcie nie może być użyte, chyba że wszystkie parametry dostarczone do przemiatania są albo taką samą liczbą kolumn, co wektor t, albo o długości 1. Popraw mnie, jeśli się mylę ...

Odpowiedz

0

Co powiesz na używanie zastosować?

t(apply(y, 1, function(x) x + v)) 
    [,1] [,2] [,3] 
[1,] 2 8 46 
[2,] 5 9 8 
[3,] 1 4 35 

Nie wiem, dlaczego zastosowanie zwraca wiersz jako columms, więc musi być transponowane.

+0

Z pełnym przekonaniem przyjrzę się mdply z pakietu plyr. To dokładnie robi to, o co prosisz. –

+0

Chciałbym zdecydowanie rzucić okiem na mdply z pakietu plyr. To dokładnie robi to, o co prosisz. –

3

Pytasz do "zamiatania" v poprzek rzędów y za pomocą funkcji "+":

sweep(y, 1, v, FUN="+") 
    v1 v2 v3 
1 2 7 44 
2 6 9 7 
3 3 5 35 
+0

Myślę, że 'MARGIN' musi być 2, ponieważ chcesz zastosować' v' do kolumn 'y'. –

+0

Tak. Też myślałem, ale oboje byliśmy w błędzie. –

+0

Myślę, że zamiatanie było dokładnie tym, czego szukałem. Problem jest w rzeczywistości bardziej złożony niż tylko dodanie wektora - użyłem tego jako przykładu, ponieważ było to najprostsze, co przyszło mi do głowy. To, czego naprawdę szukałem, to sposób na łatwe i szybkie zastosowanie funkcji wieloparametrowej do każdego rzędu - i wygląda na to, że to właśnie zamiatanie. Więc dziękuję! –

2

Nie sądzę, trzeba mapply tutaj.Wystarczy użyć t() bezpośrednio lub użyć rep() aby mecz recyklingu, jak chcesz:

> set.seed(1) 
> mat <- matrix(sample(1:100, 9, TRUE), ncol = 3) 
> vec <- 1:3 
> 
> mat 
    [,1] [,2] [,3] 
[1,] 27 91 95 
[2,] 38 21 67 
[3,] 58 90 63 
#Approach 1 using t() 
> ans1 <- t(t(mat) + vec) 
#Approach 2 using rep() 
> ans2 <- mat + rep(vec, each = nrow(mat)) 
#Are they the same? 
> identical(ans1, ans2) 
[1] TRUE 
#Hurray! 
> ans1 
    [,1] [,2] [,3] 
[1,] 28 93 98 
[2,] 39 23 70 
[3,] 59 92 66 
+0

+1 dla ręcznego recyklingu za pomocą 'rep' z' each = '. –

2

Jeśli rzeczywisty problem, to naprawdę nie ma bardziej skomplikowany niż ten, można skorzystać z zasadami recyklingu grupę R. Najpierw musisz przetransferować y, a następnie dodać, a następnie przetransponować wynik, ponieważ macierze R są przechowywane w column-major order.

t(t(y)+v) 
    v1 v2 v3 
1 2 8 46 
2 5 9 8 
3 1 4 35 
0

Chciałbym zdecydowanie rzucić okiem na mdply z pakietu plyr. To dokładnie robi to, co chcesz zrobić:

mdply(data.frame(mean = 1:5, sd = 1:5), rnorm, n = 2)