R - 使用data.table有效地测试多行和多列的滚动条件

时间:2014-05-06 17:31:17

标签: r data.table panel-data

我试图在data.table中测试各种条件,看起来像这个可重现的例子

 set.seed(17)
 year <- 1980 + rnbinom(10000,3,0.35)
 event <- rep(LETTERS, length.out=10000)
 z <- as.integer(runif(10000,min = 0, max = 10))
 dt <- data.table(event,year,z)
 setkey(dt, event,year)
 dt <- dt[,sum(z), by=c("event","year")]

V1(从最后一个命令出现)表示事件发生的次数。

因此数据表是一个有序数组,我需要在其上执行各种函数。以下是一些例子:

  1. 如何为每个事件计算前10年出现的滚动总和(或滚动平均值)?因此,对于 A 1990 期望的输出为1,452 (1980年至1989年之间)。对于 H 2012 输出为11 ,因为在2002年和2011年之间只有11次出现(2002年3次,2007年3次,2010年5次)。对于 A 1983 输出为NA

  2. 如何检查事件是否在前15年中的至少12个中发生?因此,对于 A 1997 ,我们可以看到事件发生在15年前的超过12年(1982年至1996年,它发生在除1996年以外的每年)因此标准符合。但是,对于 A 2001 ,我们看到事件只发生在前15年中的11年(1986年 - 2000年),它不会发生在1996,1998,1999和2000年)标准不是满足即可。这里所需的输出是离散1(标准符合)或0(标准不符合)

  3. 理想情况下,代码不仅可以计算years中出现的data.table,还可以计算1980年和2013年之间缺失的{{1}}。因此,对于 K 2005 ,我们可以将Q1的结果计算为25(13 + 5 + 3 + 3 + 2)(感谢@Arun指出前一个错误)。对于第二季度,我们认为事件不会发生在1999,2000,2001,2003和2004年因此标准&#34;至少在15年中的12年&#34;没有达到。此外,事件年组合可能存在于data.table中,但V1的值为0(参见第18行,A 2001)。理想情况下,这种零出现将被视为非出现(例如,通过删除V1为零的所有行)。

    我知道发布两个问题的情况并不常见,但我觉得它们属于一体,并且与类似问题有关。希望有人可以提出一些建议。

    非常感谢,

    西蒙

1 个答案:

答案 0 :(得分:3)

第一个问题:

这将获得不一定在数据集中的年份的运行总和(正如您在两点之下所要求的那样)。我们的想法是首先生成eventyear的所有组合 - 甚至是数据集中不存在的组合。这可以通过函数CJ(用于交叉连接)来完成。对于每个event,此&#39; ll会创建所有year

setkey(dt, event, year)
d1 = CJ(event=unique(dt$event), year=min(dt$year):max(dt$year))

现在,我们join返回dt以使用NA填充V1的缺失值。

d1 = dt[d1]

现在我们的数据集包含eventyear的所有组合。从这里开始,我们现在找到一种方法来执行滚动总和。为此,我们再次创建另一个数据集,其中包含了每年的所有前10年,如下所示:

window_size = 10L
d2 = d1[, list(window = seq(year-window_size, year-1L, by=1L)), by="event,year"]

对于每个&#34;事件,年份&#34;,我们会创建一个新列window,该列将生成前10年。

现在,我们要做的就是适当地设置key列并执行join以获得相应的&#34; V1&#34;值。

setkey(d2, event, window) ## note the join here is on "event, window"
setkey(d1, event, year)

ans = d1[d2]

现在,我们已经确定了&#34; V1&#34;对于每个&#34;事件,窗口&#34;组合。我们要做的就是通过&#34;事件,第1年和第34天进行汇总。 (&#34; year.1&#34;以前&#34;年&#34;和&#34;年&#34; ans之前是&#34; window&#34;)。在这里,我们处理的条件是,如果任何年份是&lt; 1980年,那么总和应该是NA。这是通过使用TRUE | NA = TRUEFALSE | NA = NA

的小型黑客来完成的
q1 = ans[, sum(V1, na.rm=TRUE) * (!any(year < 1980) | NA), by="event,year.1"]

q1[event == "K" & year.1 == "2005"]
#    event year.1 V1
# 1:     K   2005 25

关于你的第二个问题:

使用window_size = 15L而不是10L重复与上述相同的操作,直至ans。然后,我们可以做到:

q2 = ans[!is.na(V1)][, .N, by="event,year.1"]

q2[event == "A" & year.1 == 1997]
#    event year.1  N
# 1:     A   1997 14

这是正确的,因为dt有1982年至1995年的所有年份,1996年缺失,因此不计算=&gt; N=14,应该是。