【问题标题】:Rolling cross join with data.table using nested IDs and missing data使用嵌套 ID 和缺失数据与 data.table 滚动交叉连接
【发布时间】:2014-12-14 16:38:42
【问题描述】:

我有一个投资组合的数据集:

# Input test data
portolios <- structure(list(portfolioid = c(1L, 1L, 1L, 1L, 1L, 1L), secid = c("A", "B", "A", "C", "C", "A"), reportdate = c("2010-03-31", "2010-03-31", "2010-06-30", "2010-06-30", "2010-07-15", "2010-08-31"), report_type = c("Full", "Full", "Full", "Full", "Partial", "Full"), shares = c(100L, 100L, 130L, 50L, 75L, 80L)), .Names = c("portfolioid", "secid", "reportdate", "report_type", "shares"), row.names = c(NA, -6L), class = c("data.table", "data.frame"))

 portfolioid secid reportdate report_type shares
1:           1     A 2010-03-31        Full    100
2:           1     B 2010-03-31        Full    100
3:           1     A 2010-06-30        Full    130
4:           1     C 2010-06-30        Full     50
5:           1     C 2010-07-15     Partial     75
6:           1     A 2010-08-31        Full     80

我需要估算以下缺失记录:

7:           1    B 2010-06-30       Full       0
8:           1    C 2010-08-31       Full       0

业务问题是,有时未针对 Full report_type 报告职位销售(股票 = 0),因此必须根据之前的报告估算缺少的 SecID。

最终,我正在寻求从每个投资组合 ID 的先前报告中计算每个 SecID 的份额变化,以便我的数据集如下所示:

changes <- structure(list(portfolioid = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), secid = c("A", "B", "A", "B", "C", "C", "A", "C"), reportdate = c("2010-03-31", "2010-03-31", "2010-06-30", "2010-06-30", "2010-06-30", "2010-07-15", "2010-08-31", "2010-08-31"), report_type = c("Full", "Full", "Full", "Full", "Full", "Partial", "Full", "Full"), shares = c(100L, 100L, 130L, 0L, 50L, 75L, 80L, 0L), change = c(100L, 100L, 30L, -100L, 50L, 25L, -50L, -75L)), .Names = c("portfolioid", "secid", "reportdate", "report_type", "shares", "change"), row.names = c(NA, -8L), class = c("data.table", "data.frame"))

   portfolioid secid reportdate report_type shares change
1:           1     A 2010-03-31        Full    100    100
2:           1     B 2010-03-31        Full    100    100
3:           1     A 2010-06-30        Full    130     30
4:           1     B 2010-06-30        Full      0   -100
5:           1     C 2010-06-30        Full     50     50
6:           1     C 2010-07-15     Partial     75     25
7:           1     A 2010-08-31        Full     80    -50
8:           1     C 2010-08-31        Full      0    -75

不知道如何为外部连接组合[i] 创建 i。我的问题是我不想使用i &lt;- CJ(reportdate, secid),因为它会产生太多不必要的记录,因为并非每个 secid 都存在于每个 ReportDate 并且不能正确表示需要填充的数据。

我想我需要reportdate,reportdate[-1,secid] 之间的滚动交叉连接

当完整报告中缺少 secid 但它存在于之前的报告(部分或完整)中时,我想前滚 secid 并设置共享:= 0。我相信我会使用选项 roll=1 来做到这一点,但我不确定在哪里或如何实施。

我认为我的问题类似于

How to Calculate a rolling statistic in R using data.table on unevenly spaced data

我确定我缺少一些基本的理解或 CJ() 的技巧,可以创建必要的 i

【问题讨论】:

  • 您想加入portolios 什么?你的旧报告?它在哪里?你没有提供。或者您想滚动加入这两个特定的观察结果?目前还不清楚(至少对我而言)发生了什么。如果您只提供您拥有的数据集然后从连接中提供所需的输出会更容易
  • @davidarenburg 提供的唯一数据是投资组合表。我需要创建或从中派生一个要加入的表,以实现我描述的逻辑。所需的输出也显示为我提供的更改表。
  • 我不明白你怎么知道哪些是丢失的记录。您只指定shares := 0,但您怎么知道secid 和缺少的日期?例如,为什么1 B 2010-08-31 Full 0 也没有丢失?
  • @davidarenburg 丢失的记录必须基于此规则进行估算:如果 secid 存在于先前的 reportdate 中但在以下 Full reportdate 中丢失,则此 secid 应该是结转和shares:=0。诀窍是如何计算应该从先前的reportdate 结转哪个secid。这就是为什么我相信roll=1 可能是解决方案的一部分。
  • @davidarenburg 1 B 2010-08-31 Full 0 没有丢失的原因是因为 B 不在输入数据集中 2010-06-30 的先前报告中。您也可以将其视为只想延续到下一个时期secid 其中shares &lt;&gt; 0。您不想结转 shares = 0 的填充缺失值

标签: r data.table


【解决方案1】:

这样的事情应该可以工作(如果我理解正确的话)

首先设置reportdate 与日期类。还可以获得唯一的日期

portolios[, reportdate := as.IDate(reportdate)]
uniq.dts <- unique(portolios$reportdate)
uniq.dts <- uniq.dts[order(uniq.dts)]

对每个 i 执行自联接,并仅提取在我们知道 secid 已经存在之后发生的日期(应该比 CJ 更节省内存)

setkey(portolios,secid)
setorder(portolios,sec,id,reportdate)

impute <- portolios[portolios, {
      tmp = max(reportdate) < uniq.dts;
        list(portfolioid=1,reportdate=uniq.dts[tmp][1],report_type="Full",shares=0)
},by=.EACHI][!is.na(reportdate)][,.SD[1],by=secid]

接下来,rbindlist 原始表和impute 表。

portolios <- rbindlist(list(portolios,impute),fill=TRUE)

#Order data by secid and reportdate
portolios <- portolios[order(secid,reportdate)]

#Lag data by group
portolios[, prev.shares := c(NA,lag(shares)), by=secid]

#Calculate change WHEN a previous share amount exists
portolios[, change := ifelse(is.na(prev.shares),shares,shares-prev.shares), by=secid]

print(portolios[order(reportdate)])
   portfolioid secid reportdate report_type shares prev.shares change
1:           1     A 2010-03-31        Full    100          NA    100
2:           1     B 2010-03-31        Full    100          NA    100
3:           1     A 2010-06-30        Full    130         100     30
4:           1     B 2010-06-30        Full      0         100   -100
5:           1     C 2010-06-30        Full     50          NA     50
6:           1     C 2010-07-15     Partial     75          50     25
7:           1     A 2010-08-31        Full     80         130    -50
8:           1     C 2010-08-31        Full      0          75    -75

【讨论】:

  • 感谢@mike.gahan,这很接近,但是您如何在portfolios 结果中创建行4: 1 B 2010-06-30 Full 0 100 -1008: 1 C 2010-08-31 Full 0 75 -75?原始portfolios 结构中缺少这些行,需要估算/创建,设置共享:= 0。创建这些缺少的行是我坚持的部分。
  • 那么C 2010-08-31 也需要估算吗?如果不是,为什么?
  • 是的 .. 我的 portfolios 输入数据中有 6 行,我想要的结果中有 8 行。如果secid 存在于先前的reportdate 中,但在随后的Full 中缺少reportdate 相同的portfolio,则缺少的shares 将替换为0。挑战在于填补缺失的secid
  • 我想我现在理解得更好了。对每个 i 而不是 CJ 进行自连接可能很有用。
  • 在创建impute 时,例程是否通过portfolioid 进行迭代?试图更好地理解这一行list(portfolioid=1,reportdate=uniq.dts[tmp][1],report_type="Full",shares=0) },by=.EACHI
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2017-10-23
  • 2018-02-20
  • 2020-09-30
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
相关资源
最近更新 更多