2010-12-09 58 views
2

ContexteComment puis-je réécrire ce code afin qu'il utilise plyr/ddply comme prévu?

J'ai dataframe des distributions de probabilité que je voudrais calculer des résumés statistiques pour:

priors <- structure(list(name = c("theta1", "theta2", "theta3", "theta4", 
    "theta5"), distn = c("gamma", "beta", "lnorm", "weibull", "gamma"), 
    parama = c(2.68, 4, 1.35, 1.7, 2.3), paramb = c(0.084, 7.2, 0.69, 0.66, 3.9), 
    another_col = structure(c(3L, 4L, 5L, 1L, 2L 
    ), .Label = c("1", "2", "a", "b", "c"), class = "factor")), 
    .Names = c("name", "distn", "parama", "paramb", "another_col"), row.names = c("1", 
    "2", "3", "4", "5"), class = "data.frame") 

approche

Étape 1: J'ai écrit une fonction pour calculer la sommaires et retour mean(lcl, ucl)

summary.stats <- function(distn, A, B) { 
    if (distn == 'gamma' ) ans <- c(A*B,      qgamma(c(0.05, 0.95), A[ ], B)) 
    if (distn == 'lnorm' ) ans <- c(exp(A + 1/2 * B^2),  qlnorm(c(0.05, 0.95), A, B)) 
    if (distn == 'beta' ) ans <- c(A/(A+B),     qbeta(c(0.05, 0.95), A, B)) 
    if (distn == 'weibull') ans <- c(mean(rweibull(10000,A,B)), qweibull(c(0.05, 0.95), A, B)) 
    if (distn == 'norm' ) ans <- c(A,       qnorm(c(0.05, 0.95), A, B)) 
    ans <- (signif(ans, 2)) 
    return(paste(ans[1], ' (', ans[2], ', ', ans[3],')', sep = '')) 
} 

Étape 2: Je voudrais ajouter une nouvelle colonne à mon dataframe appelé stats

priors$stats <- ddply(priors, 
        .(name, distn, parama, paramb), 
        function(x) summary.stats(x$distn, x$parama, x$paramb))$V1 

Question 1:

quelle est la bonne façon de le faire? Je reçois une erreur lorsque je tente

   ddply(priors, 
        .(name, distn, parama, paramb), 
        transform, 
        stats = function(x) summary.stats(x$distn, x$parama, x$paramb)) 

Question 2: (crédit supplémentaire)

est-il un moyen plus efficace de coder la fonction summary.stats, à savoir, avec moins « si ce »?

mise à jour

Merci à Shane et Joshua pour cette compensation pour moi.

Je trouve aussi une question qui devrait être utile pour les autres essayant de do a plyr operation on every row of a dataframe

Répondre

4

Voici une version assainis de votre summary.stats qui utilise à la place switch. J'ai également ajouté le nom "stats" à la sortie, car cela semble être la chose qui vous fait trébucher.

summaryStats <- function(distn, A, B) { 
    CI <- c(0.05, 0.95) 
    FUN <- get(paste("q",distn,sep="")) 
    ans <- switch(distn, 
    gamma = A*B, 
    lnorm = exp(A + 1/2 * B^2), 
    beta = A/(A+B), 
    weibull = mean(rweibull(10000,A,B)), 
    norm = A) 
    ans <- c(ans, FUN(CI, A, B)) 
    ans <- (signif(ans, 2)) 
    out <- c(stats=paste(ans[1], ' (', ans[2], ', ', ans[3],')', sep='')) 
    return(out) 
} 

Je ne suis pas sûr de savoir comment faire avec plyr, mais vous pouvez le faire avec ol ennuyeux » sapply comme ceci:

priors$stats <- sapply(1:nrow(priors), 
    function(i) with(priors[i,], summaryStats(distn, parama, paramb))) 
4

je ne pouvais manquer quelque chose, mais en utilisant la fonction de Josh et vos données, cela fonctionne bien.

priors <- ddply(priors, 
    .(name, distn, parama, paramb), 
    function(x) summaryStats(x$distn, x$parama, x$paramb)) 
colnames(priors)[5] <- "stats" 

À quoi voulez-vous que votre sortie ressemble?

> priors 
    name distn parama paramb   stats 
1 theta1 gamma 2.68 0.084 0.23 (7.8, 69) 
2 theta2 beta 4.00 7.200 0.36 (0.15, 0.6) 
3 theta3 lnorm 1.35 0.690 4.9 (1.2, 12) 
4 theta4 weibull 1.70 0.660 0.59 (0.12, 1.3) 
5 theta5 gamma 2.30 3.900 9 (0.12, 1.3) 

Modifier

Désolé, n'a pas lu tout commentaire. Alors cela devrait fonctionner (dans mon exemple ici, je laisse de côté une colonne):

ddply(priors, .(distn, parama, paramb), function(x) 
    data.frame(x, stats=summaryStats(x$distn, x$parama, x$paramb))) 
+0

Je pense qu'il veut que le nouveau nom de colonne soit "stats". J'ai ajouté cela à ma version de sa fonction. –

+0

@Shane, merci pour votre réponse.Ce que je suis confus sur est comment obtenir 'ddply' pour sortir une seule colonne que je peux assigner à une nouvelle colonne dans les priors, par exemple. 'priors $ stats <- ddply (....) $ V1'; Je suppose que l'utilisation de 'ddply() $ V1' n'est pas correcte. L'élément de données «priors» «priors» a d'autres colonnes que je voudrais conserver sans avoir à toutes les spécifier dans 'ddply()'. –

+0

@David Exécutez mon code. 'ddply' * fait * ça automatiquement. – Shane