Come posso riscrivere il codice in modo che utilizzi plyr / ddply come previsto?
-
25-09-2019 - |
Domanda
Sfondo
Ho un dataframe di distribuzioni di probabilità che vorrei calcolare rilevazioni statistiche per:
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")
Approccio
Passaggio 1: Ho scritto una funzione per calcolare le sintesi ei mean(lcl, ucl)
ritorno
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 = ''))
}
Passaggio 2: vorrei aggiungere una nuova colonna alla mia dataframe chiamato stats
priors$stats <- ddply(priors,
.(name, distn, parama, paramb),
function(x) summary.stats(x$distn, x$parama, x$paramb))$V1
Domanda 1:
qual è il modo corretto di fare questo? Ottengo un errore quando provo
ddply(priors,
.(name, distn, parama, paramb),
transform,
stats = function(x) summary.stats(x$distn, x$parama, x$paramb))
Domanda 2: (credito extra)
C'è un modo più efficiente per il codice della funzione summary.stats
, vale a dire con meno 'se di'?
update
Grazie a Shane e Joshua per rimozione di questo per me.
Ho anche trovato una domanda che dovrebbe essere utile per gli altri cercando di eseguire un'operazione plyr su ogni riga di una dataframe
Soluzione
Ecco una versione ripulita del vostro summary.stats
che usi switch
invece. Ho anche aggiunto il nome di "stats" per l'uscita, dal momento che sembra essere la cosa che inciampare.
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)
}
Non sono sicuro di come fare questo con plyr
, ma è possibile farlo con noioso ol' sapply
in questo modo:
priors$stats <- sapply(1:nrow(priors),
function(i) with(priors[i,], summaryStats(distn, parama, paramb) ))
Altri suggerimenti
potrei mancare qualcosa, ma utilizzando la funzione di Josh ei dati, questo funziona bene.
priors <- ddply(priors,
.(name, distn, parama, paramb),
function(x) summaryStats(x$distn, x$parama, x$paramb))
colnames(priors)[5] <- "stats"
Che cosa volete che il vostro uscita a guardare come?
> 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)
Modifica
Siamo spiacenti, non ha letto tutto il tuo commento. Quindi questo dovrebbe funzionare (nel mio esempio qui, lascio fuori una colonna):
ddply(priors, .(distn, parama, paramb), function(x)
data.frame(x, stats=summaryStats(x$distn, x$parama, x$paramb)))