2011-01-21 17 views
11

Mam listę funkcjiZastosuj listę n funkcji do każdego wiersza ramki danych?

funs <- list(fn1 = function(x) x^2, 
      fn2 = function(x) x^3,    
      fn3 = function(x) sin(x), 
      fn4 = function(x) x+1) 
#in reality these are all f = splinefun() 

I mam dataframe:

mydata <- data.frame(x1 = c(1, 2, 3, 2), 
        x2 = c(3, 2, 1, 0), 
        x3 = c(1, 2, 2, 3), 
        x4 = c(1, 2, 1, 2)) 
#actually a 500x15 dataframe of 500 samples from 15 parameters 

dla każdego z I rzędach, chciałbym funkcja oceny j na każdym z j kolumn i suma wyników:

unlist(funs) 
attach(mydata) 
a <- rep(NA,4) 
for (i in 1:4) { 
    a[i] <- sum(fn1(x1[i]), fn2(x2[i]), fn3(x3[i]), fn4(x4[i])) 
} 

Jak mogę to zrobić wydajnie? Czy jest to odpowiednia okazja do wdrożenia funkcji plyr? Jeśli tak to jak?

pytanie dodatkowe: dlaczego jest a[4]NA?

Czy jest to odpowiedni czas na korzystanie z funkcji od plyr, jeśli tak, w jaki sposób mogę to zrobić?

+1

@ na trzecim fragmencie kodu, musisz albo "unlist (funs)" i "dołączyć (mydata)' lub użyć 'funs $ fn1' i' mydata $ x1' –

+0

@ David podziękowania za korektę, I zmienili kod, aby to odzwierciedlić, ale to jest właśnie niechlujstwo, którego chciałbym uniknąć. – Abe

+2

Cóż, dla punktu bonusowego odpowiedź brzmi, że nie ma czwartego elementu w mydata $ x4 lub żadnej z kolumn tej ramki danych. Kolejny komentarz ... po prostu wpisując unlist (funs) nic nie robi, chyba że przypisujesz wynik do czegoś. Witamy w programowaniu funkcjonalnym. –

Odpowiedz

9

Ignorując swój fragment kodu i trzymanie się swojej pierwotnej specyfikacji, które chcesz zastosować funkcję j na numer kolumny j a następnie „Podsumowując wyniki” ... można zrobić:

mapply(do.call, funs, lapply(mydata, list)) 
#  [,1] [,2]  [,3] [,4] 
# [1,] 1 27 0.8414710 2 
# [2,] 4 8 0.9092974 3 
# [3,] 9 1 0.9092974 3 

Nie byłem pewien, w jaki sposób chcesz teraz dodać wyniki (np. Wierszowo lub kolumnowo), więc możesz zrobić rowSums lub colSums na tej macierzy. E.g:

colSums(mapply(do.call, funs, lapply(mydata, list))) 
# [1] 14.000000 36.000000 2.660066 8.000000 
+0

dzięki za pomoc; Będę używał rowSums, ale to jest koncepcja, której szukałem. – Abe

+0

Nie rozumiem, co robi ostatnia lista, nie jest drugim argumentem do zrobienia. Otwórz listę argumentów do funkcji? – Abe

+0

Edytowałem drugie wyrażenie nieco wyżej (nie musisz wykonywać 'as.list'). Musisz zrobić 'lapply (mydata, list)', aby zmienić 'mydata' na listę list. Następnie 'mapply' powoduje' do.call', aby wziąć każdą funkcję w 'funs', i bierze odpowiedni element listy' lapply (mydata, list) ', który sam jest listą. –

4

Dlaczego po prostu nie napisać jednej funkcji dla wszystkich 4 i zastosować ją do ramki danych? wszystkich funkcji są wektorowy, a więc jest splinefun, a to będzie działać:

fun <- function(df) 
    cbind(df[, 1]^2, df[, 2]^3, sin(df[, 3]), df[, 4] + 1) 

rowSums(fun(mydata)) 

To jest znacznie bardziej efektywne niż „foring” lub „nakładanie” nad rzędami.

0

Próbowałem za pomocą plyr::each:

library(plyr) 
sapply(mydata, each(min, max)) 
    x1 x2 x3 x4 
min 1 0 1 1 
max 3 3 3 2 

i działa dobrze, ale gdy mijam funkcje niestandardowe uzyskać:

sapply(mydata, each(fn1, fn2)) 
Error in proto[[i]] <- fs[[i]](x, ...) : 
    more elements supplied than there are to replace 

each ma bardzo krótką dokumentację, nie dość dostać co problem.

Powiązane problemy