【问题标题】:R - Using data.table to efficiently test rolling conditions across multiple rows and columnsR - 使用 data.table 有效地测试跨多行和多列的滚动条件
【发布时间】:2014-06-23 10:54:04
【问题描述】:

我正在尝试在一个看起来像这个可重现示例的 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(不符合标准)

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

我知道发布两个问题并不常见,但我觉得它们属于同一类,并且确实与类似的问题相关。希望有人能提出一些建议。

非常感谢,

西蒙

【问题讨论】:

  • 你是对的。似乎我的 set.seed() 出于某种原因没有工作。该死的很烦人。我将不得不更新我提到的每个值:(
  • @Arun 是的,这是正确的。不知道我从哪里得到 10,如果我忘记了第一个或最后一个,那甚至都不是一个选择。道歉
  • 嗨,我期望 A, 1983 为 NA 的原因要简单得多。在 1983 年之前,我没有 10 年的数据。(我的完整数据集始于 1980 年。我打算用它来定义过去经常发生的事件。在实际结果中,我将面板减少到 1990 年 - 2006 年。之后的年份用于样本外预测,而之前的年份(1980-1989)用于创建此类历史频率。
  • 关于例如Z, 2012我理解这种困惑。我有一个实际包含 2013 年的数据集。但正如虚假数据所示,事件的发生率在接近尾声时急剧下降。所以简而言之,2012 年可能存在于我的数据中并需要一个值,但我不能追溯到 1980 年以后,因此 1989 年之前的每个滚动平均值都不能有 10 年之前的信息。 (根据调查结果,我会将其调整为 7 年或 8 年或 11 年)......希望这能澄清它并非常感谢您的努力!

标签: r data.table panel-data


【解决方案1】:

第一个问题:

这将获得不一定在数据集中的年份的运行总和(正如您在两点下方所要求的那样)。这个想法是首先生成eventyear 的所有组合——即使是数据集中不存在的组合。这可以通过函数CJ(用于交叉连接)来完成。这将为每个event 创建所有year

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

现在,我们将joindt 返回以用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"]

对于每个“事件,年份”,我们创建一个新列 window,它将生成前 10 年。

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

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

ans = d1[d2]

现在,我们为每个“事件、窗口”组合提供了“V1”的值。我们要做的就是按“event,year.1”聚合(“year.1”之前是“year”,ans 中的“year”之前是“window”)。在这里,我们要考虑的条件是,如果任何年份 TRUE | NA = TRUE 和FALSE | 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 年缺失,因此未计算在内 => N=14,应该如此。

【讨论】:

  • 非常感谢您的解决方案和非常清晰的解释。它在我的数据集上表现出色!喜欢窗口大小和 TRUE | NA技巧。将来肯定会使用它们!
猜你喜欢
  • 1970-01-01
  • 2014-03-02
  • 2020-07-08
  • 2014-09-30
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多