2

我有一个长数据框,其中包含三列fyearticdcvt(用于财政年度、股票代码和可转换债务总额)。大约有 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吗?如果可以的话,我想避免通过时间序列。谢谢!

4

2 回答 2

5

在 ddply 中使用 transform 有时对我们有很大帮助:

ddply(temp, .(tic), transform, dcvt=c(0, diff(dcvt)>0))
于 2011-02-26T00:11:29.953 回答
2

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))

为了展示性能回报(考虑到向量与数据帧的问题,不公平),我获取了 OP 的样本数据,创建了大小为 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()- 而是努力分享一些我最近在处理一个非常相似的问题时发现有用的代码,其中包含一个非常大的数据集。

于 2011-02-26T16:07:01.387 回答