Можно ли повторно использовать сгенерированные столбцы в ddply? - PullRequest
4 голосов
/ 30 июля 2010

У меня есть скрипт, в котором я использую ddply, как в следующем примере:

ddply(df, .(col),
function(x) data.frame(
col1=some_function(x$y),
col2=some_other_function(x$y)
)
)

Возможно ли в ddply повторно использовать col1 без повторного вызова всей функции?

Например:

ddply(df, .(col),
function(x) data.frame(
col1=some_function(x$y),
col2=some_other_function(x$y)
col3=col1*col2
)
)

Ответы [ 3 ]

5 голосов
/ 30 июля 2010

У вас есть целая функция для игры! Не должен быть однострочником! Это должно работать:

ddply(df, .(col), function(x) {
  tmp <- some_other_function(x$y)
  data.frame(
    col1=some_function(x$y),
    col2=tmp,
    col3=tmp
  )
})
3 голосов
/ 20 сентября 2012

Это хороший кандидат для data.table с использованием правил области действия компонента j.Подробнее см. FAQ 2.8 .

Из FAQ

Анонимная функция не передается j.Вместо этого анонимное тело передается в j.

Итак, для вашего случая

library(data.table)
DT <- as.data.table(df)
DT[,{
 col1=some_function(y)
 col2=some_other_function(y)
 col3= col1 *col2
 list(col1 = col1, col2 = col2, col3 = col3)
 }, by = col]  

или чуть более прямой путь:

DT[,list(
 col1=col1<-some_function(y)
 col2=col2<-some_other_function(y)
 col3=col1*col2
 ), by = col]  

Это позволяет избежать одного повторения каждого из col1 и col2 и избежать двух повторений col3;повторение - это то, что мы стремимся уменьшить в data.table.=, за которым следует <-, на первый взгляд могут показаться громоздкими.Это позволяет использовать следующий синтаксический сахар:

DT[,list(
 "Projected return (%)"=      col1<-some_function(y),
 "Investment ($m)"=           col2<-some_other_function(y),
 "Return on Investment ($m)"= col1*col2
 ), by = col]  

, где вывод может быть отправлен напрямую, например, в латекс или html.

2 голосов
/ 30 июля 2010

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

#use summarize() in ddply()
data.means <- ddply(data, .(groups), summarize, mean = mean(x), sd = sd(x), n = length(x))
data.means$se <- data.means$sd / sqrt(data.means$n)
data.means$Upper <- data.means$mean + (data.means$SE * 1.96)
data.means$Lower <- data.means$mean - (data.means$SE * 1.96)

Так что я не вычислял SE напрямую, но это было не так плохо, вычисляя его вне ddply(). Если бы вы действительно хотели, вы могли бы также сделать

ddply(data, .(groups), summarize, se = sd(x) / sqrt(length(x)))

Или, если сравнивать с вашим примером

ddply(df, .(col), summarize,
      col1=some_function(y),
      col2=some_other_function(y)
      col3=some_function(y)*some_other_function(y)
    )
...