Appliquer une liste de n fonctions à chaque rangée d'une trame de données?

StackOverflow https://stackoverflow.com/questions/4765053

  •  16-10-2019
  •  | 
  •  

Question

J'ai une liste de fonctions

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

Et j'ai 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

Pour chacun des i lignes, je voudrais évaluer la fonction j sur chacun des j colonnes et additionner les résultats:

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

Comment puis-je faire cela efficacement? Est-ce une bonne occasion de mettre en œuvre des fonctions de plyr? Si oui, comment?

question bonus: pourquoi est-a[4] NA

Est-ce un bon moment pour utiliser les fonctions de plyr, si oui, comment puis-je faire?

Était-ce utile?

La solution

Ignorer l'extrait de code et coller à votre spécification initiale que vous souhaitez appliquer la fonction j sur le numéro de colonne j et « la somme des résultats » ... vous peut faire:

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

je ne savais pas de quelle façon vous voulez ajouter maintenant les résultats (à savoir rangée ou par colonne-sage), de sorte que vous pouvez soit faire rowSums ou colSums sur cette matrice. Par exemple:

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

Autres conseils

Pourquoi ne pas simplement écrire une fonction pour tous les 4 et l'appliquer à la trame de données? Toutes vos fonctions sont vectorisés, et ainsi est splinefun, et cela fonctionne:

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

rowSums(fun(mydata))

Ceci est beaucoup plus efficace que « pourING » ou « application » sur les lignes.

J'ai essayé d'utiliser plyr::each:

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

et il fonctionne très bien, mais quand je passe des fonctions personnalisées je reçois:

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

each dispose d'une documentation très bref, je ne comprends pas tout à fait ce qui est le problème.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top