2011-01-21 5 views
11

У меня есть список функцийПрименять список n функций к каждой строке кадра данных?

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() 

И у меня есть 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 

Для каждого из I строк, я хотел бы, чтобы оценить функцию J на каждом из j и суммировать результаты:

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])) 
} 

Как я могу сделать это эффективно? Это подходящий случай для реализации функций plyr? Если да, то как?

вопрос бонуса: почему a[4]NA?

Это подходящее время для использования функций от plyr, если да, то как я могу это сделать?

+1

@abe для третьего фрагмента кода, вам нужно либо «unlist (funs)», либо «attach (mydata)» или использовать 'funs $ fn1' и' mydata $ x1' –

+0

@ David благодарит за исправление, I изменили код, чтобы отразить это, но это именно беспорядок, которого я бы хотел избежать. – Abe

+2

Ну, для бонусной точки ответ заключается в том, что в mydata $ x4 нет ни одного элемента, ни одного из столбцов этого фрейма. Еще один комментарий .. просто ввод unlist (funs) ничего не делает, если вы не присваиваете результат чему-либо. Добро пожаловать в функциональное программирование. –

ответ

9

Игнорирование фрагмента кода и приклеить к вашей начальной спецификации, которые вы хотите применить функцию J на колонке числе J, а затем «подвести итоги» ... вы можете сделать:

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 

Я не был уверен, каким образом вы хотите добавить результаты (например, по строкам или по столбцам), так что вы можете либо сделать rowSums, либо colSums на этой матрице. Например:

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

спасибо за эту помощь; Я буду использовать rowSums, но это концепция, которую я искал. – Abe

+0

Я не понимаю, что делает последний список, это не второй аргумент do.call список аргументов функции? – Abe

+0

Я немного изменил второе выражение (вам не нужно делать 'as.list'). Вам нужно сделать 'lapply (mydata, list)', чтобы превратить 'mydata' в список списков. Затем 'mapply' заставляет' do.call' принимать каждую функцию в 'funs' и принимает соответствующий список-член' lapply (mydata, list) ', который сам является списком. –

4

Почему бы не просто написать одну функцию для всех 4 и применить ее к кадру данных? Все ваши функции векторизации и так splinefun, и это будет работать:

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

rowSums(fun(mydata)) 

Это значительно эффективнее, чем «foring» или «применения» по рядам.

0

Я попытался с помощью plyr::each:

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

и она отлично работает, но когда я прохожу пользовательские функции я получаю:

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

each имеет очень короткую документацию, я не совсем понимаю, что это проблема.