Как я могу переписать этот код, чтобы он использовал plyr / ddply, как предполагалось? - PullRequest
2 голосов
/ 10 декабря 2010

Фон

У меня есть план распределения вероятностей, для которого я хотел бы рассчитать статистические сводки:

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, т. Е. С меньшим количеством «если»?

обновление

Спасибо Шейну и Джошуа за разъяснение этого для меня.

Я также нашел вопрос, который может быть полезен для других, пытающихся выполнить операцию plyr для каждой строки кадра данных

Ответы [ 2 ]

4 голосов
/ 10 декабря 2010

Я мог бы что-то упустить, но используя функцию Джоша и ваши данные, это прекрасно работает.

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)))
4 голосов
/ 10 декабря 2010

Вот очищенная версия вашего summary.stats, в которой вместо этого используется switch.Я также добавил название «статистика» к выводу, так как кажется, что это вас смущает.

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, но вы можетеэто со скучным старым sapply вот так:

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