[英]How can I improve the performance of my data cleaning code that currently uses ddply by using data.table?
[英]How can I rewrite this code so that it uses plyr/ddply as intended?
背景
我有一個概率分布的數據框,我想計算統計摘要:
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")
途徑
第1步:我寫了一個函數來計算摘要和返回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 = ''))
}
第2步:我想在我的數據框中添加一個名為stats
的新列
priors$stats <- ddply(priors,
.(name, distn, parama, paramb),
function(x) summary.stats(x$distn, x$parama, x$paramb))$V1
問題1:
這樣做的正確方法是什么? 我嘗試時收到錯誤
ddply(priors,
.(name, distn, parama, paramb),
transform,
stats = function(x) summary.stats(x$distn, x$parama, x$paramb))
問題2 :(額外信貸)
是否有更有效的方法來編碼summary.stats
函數,即使用較少的'if's?
更新
感謝Shane和Joshua為我清理這件事。
我還發現了一個問題,對於試圖在數據幀的每一行上進行plyr操作的其他人來說應該是有用的
這是使用switch
的summary.stats
的清理版本。 我還在輸出中添加了名稱“stats”,因為這似乎是絆倒你的事情。
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)
}
我不知道如何用plyr
做到這plyr
,但是你可以像這樣無聊地sapply
這個:
priors$stats <- sapply(1:nrow(priors),
function(i) with(priors[i,], summaryStats(distn, parama, paramb) ))
我可能會遺漏一些東西,但是使用Josh的功能和你的數據,這很好。
priors <- ddply(priors,
.(name, distn, parama, paramb),
function(x) summaryStats(x$distn, x$parama, x$paramb))
colnames(priors)[5] <- "stats"
您希望輸出看起來像什么?
> 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)
編輯
對不起,沒看完你的評論。 然后這應該工作(在我的例子中,我留下一列):
ddply(priors, .(distn, parama, paramb), function(x)
data.frame(x, stats=summaryStats(x$distn, x$parama, x$paramb)))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.