Добавьте переменную индикатора в длинный фрейм данных, когда значение увеличивается от одного года к следующему - PullRequest
2 голосов
/ 26 февраля 2011

У меня длинный фрейм данных с тремя столбцами fyear, tic и dcvt (для финансового года, тикера и общего конвертируемого долга). Есть около 18 финансовых лет и несколько тысяч тикеров. Я хотел бы добавить переменную-индикатор, равную единице, когда dcvt увеличивается от года к году.

Я пытался ddply, но я потерял столбец fyear и не знал, как его вернуть.

library(plyr)
temp <- data.frame(fyear = rep(1992:2009, 10), tic = rep(letters[1:10], each = 18), dcvt = rnorm(180, 200, 10))
my.fun <- function(x) x <- c(0, ifelse(tail(x, -1) - head(x, -1) > 0, 1, 0))
temp2 <- ddply(temp, "tic", colwise(my.fun, "dcvt"))

Я также пытался привести к широкому с помощью пакета reshape2, затем запустить for циклы, но, конечно, это заняло вечность.

Есть ли способ, которым я могу сделать это быстро? Должен ли я сделать широкий zoo объект, а затем использовать diff? Я хотел бы избежать прохождения временного ряда, если смогу. Спасибо!

Ответы [ 2 ]

5 голосов
/ 26 февраля 2011

использование transform в ddply иногда очень помогает нам:

ddply(temp, .(tic), transform, dcvt=c(0, diff(dcvt)>0))
2 голосов
/ 26 февраля 2011

ddpy() довольно хорошо обрабатывает набор данных такого размера (10 ^ 2).Однако для больших наборов данных и для ситуаций, когда вам необязательно возвращать полный фрейм данных, я бы рассмотрел следующее решение do.call + lapply:

my.fun <- function(cur.tic){
  as.numeric(diff(temp$dcvt[temp$tic == cur.tic]) > 0)
}

do.call("c", lapply(unique(temp$tic), my.fun))

Чтобы продемонстрировать выигрыши в производительности (несправедливо учитывая проблему вектора и данных), я взял образцы данных ОП, создал новые кадры данных величин 10 ^ 4, 10 ^ 5 и 10 ^ 6, а затем запустил system.time() для решения @ kohske ddply ирешение выше:

Исходные данные (10 ^ 2):

> system.time(do.call("c", lapply(unique(temp$tic), my.fun)))
   user  system elapsed 
  0.000   0.000   0.003 
> system.time(ddply(temp, .(tic), transform, dcvt=c(0, diff(dcvt)>0)))
   user  system elapsed 
  0.020   0.000   0.013 

10 ^ 4 выборочных данных

> system.time(do.call("c", lapply(unique(temp.2$tic), my.fun)))
   user  system elapsed 
  0.000   0.000   0.002 
> system.time(ddply(temp.2, .(tic), transform, dcvt=c(0, diff(dcvt)>0)))
   user  system elapsed 
  0.040   0.000   0.036 

10 ^ 5 выборочных данных

> system.time(do.call("c", lapply(unique(temp.3$tic), my.fun)))
   user  system elapsed 
  0.000   0.000   0.004 
> system.time(ddply(temp.3, .(tic), transform, dcvt=c(0, diff(dcvt)>0)))
   user  system elapsed 
  0.270   0.000   0.279 

10 ^ 6 примеров данных

> system.time(do.call("c", lapply(unique(temp.4$tic), my.fun)))
   user  system elapsed 
  0.010   0.000   0.018 
> system.time(ddply(temp.4, .(tic), transform, dcvt=c(0, diff(dcvt)>0)))
   user  system elapsed 
  6.110   0.070   6.186 

Не жалко о ddply() - скорее, просто попытка поделиться кодом, который я нашел полезным, работая над очень похожей проблемой с оченьНабор данных Larget недавно.

...