R 具有两个标识符的事件的重叠周期
R Overlapping period for event with two identifiers
我正在尝试为具有两个标识符的数据框查找重叠周期,这与在该主题上提出的其他问题不同,在这些问题中,重叠观察必须只计算一个标识符。
在我的数据框中,每笔交易都有一个唯一的 ID,每家进行交易的公司都有一个唯一的公司标识符。我正在尝试查找每个公司标识符的重叠周期,按交易 ID 计算。
我使用来自@Waldi 的代码创建了这个可重现的示例,在本主题中找到(我只向示例数据框添加了公司标识符或“FirmID”):
创建类似数据集的代码:
library (data.table)
size = 1e5
df <- data.frame(
ID = sample(1:round(size / 5, 0)),
FirmID = sample(1:20000),
period = sample(c(5,10,30,45), size, replace = TRUE),
start = sample(seq(
as.Date('1999/01/01'), as.Date('2000/01/01'), by = "day"
), size, replace = TRUE)
) %>% mutate(end = start + period)
查找重叠时段的代码:
dt <- data.table(df, key = c("start", "end"))[, `:=`(row = 1:nrow(df))]
setkey(dt,FirmID,start,end)
foverlaps(dt,dt,by.x=c("FirmID","start","end"),by.y=c("FirmID","start","end"))[
,.(noverlap=.N),by=.(FirmID,row)][
,.(overlap = max(noverlap>1)),by=FirmID][
,.(n=.N),by=.(overlap)][
,pct:=n/sum(n)][]
此代码的唯一问题是它显示重叠公司的数量,而不是公司标识符内重叠交易的数量。
overlap n pct
1: 0 5333 0.26665
2: 1 14667 0.73335
如何针对公司标识符中重叠的交易 ID 更改此代码?我自己做的一个改变没有产生令人满意的结果:
setkey(dt,FirmID,start,end)
foverlaps(dt,dt,by.x=c("FirmID","start","end"),by.y=c("FirmID","start","end"))[
,.(noverlap=.N),by=.(ID,row)][
,.(overlap = max(noverlap>1)),by=ID][
,.(n=.N),by=.(overlap)][
,pct:=n/sum(n)][]
overlap n pct
1: 0 5333 0.26665
2: 1 14667 0.73335
我费了好大劲才想出另一种情况的解决方案,
所以我不确定如何调整那个版本,
但我相信在这种情况下你可以通过内部 non-equi join:
获得你想要的结果
dt <- data.table(df, key = c("FirmID", "ID", "start", "end"))
dt[, firm_total := .N, by = "FirmID"][
dt, .(FirmID, firm_total), on = .(FirmID, ID < ID, start <= end, end >= start), nomatch = NULL, mult = "all"][
, .(n = .N, pct = .N / (firm_total[1L] * (firm_total[1L] - 1L) / 2L)), by = "FirmID"]
我们在与 ID < ID
的连接中避免了冗余行
(请注意,此处应解释为 left-hand side column's ID < right-hand side column's ID)。
冗余可能发生,因为,
如果 ID x
与 ID y
重叠,
y
与 x
重叠。
如果你把所有的ID对放到一个矩阵中,
重叠的最大数量将是下三角中的元素数量,
可以用 n * (n - 1) / 2
计算,
这就是我们最初添加 firm_total
.
的原因
我没有进行广泛的测试,但这个版本可能更适合这种情况。
foverlaps
的文档指出它主要针对一个 table 比另一个小得多的连接,
并解释为什么它可能是一项昂贵的操作。
你正在做 self-join,
所以两个 table 大小相同。
还有一个 table.express
版本的解决方案,因为为什么不:
library(table.express)
dt %>%
group_by(FirmID) %>%
mutate(firm_total = .N) %>%
inner_join(dt, FirmID, ID < ID, start <= end, end >= start, .expr = TRUE) %>%
select(FirmID, firm_total) %>%
group_by(FirmID) %>%
summarize(n = .N, pct = .N / (firm_total[1L] * (firm_total[1L] - 1L) / 2))
编辑:如果你想要你的 overlap
列,你可以用 size of lower triangular - n
.
计算它
我正在尝试为具有两个标识符的数据框查找重叠周期,这与在该主题上提出的其他问题不同,在这些问题中,重叠观察必须只计算一个标识符。
在我的数据框中,每笔交易都有一个唯一的 ID,每家进行交易的公司都有一个唯一的公司标识符。我正在尝试查找每个公司标识符的重叠周期,按交易 ID 计算。
我使用来自@Waldi 的代码创建了这个可重现的示例,在本主题中找到(我只向示例数据框添加了公司标识符或“FirmID”):
创建类似数据集的代码:
library (data.table)
size = 1e5
df <- data.frame(
ID = sample(1:round(size / 5, 0)),
FirmID = sample(1:20000),
period = sample(c(5,10,30,45), size, replace = TRUE),
start = sample(seq(
as.Date('1999/01/01'), as.Date('2000/01/01'), by = "day"
), size, replace = TRUE)
) %>% mutate(end = start + period)
查找重叠时段的代码:
dt <- data.table(df, key = c("start", "end"))[, `:=`(row = 1:nrow(df))]
setkey(dt,FirmID,start,end)
foverlaps(dt,dt,by.x=c("FirmID","start","end"),by.y=c("FirmID","start","end"))[
,.(noverlap=.N),by=.(FirmID,row)][
,.(overlap = max(noverlap>1)),by=FirmID][
,.(n=.N),by=.(overlap)][
,pct:=n/sum(n)][]
此代码的唯一问题是它显示重叠公司的数量,而不是公司标识符内重叠交易的数量。
overlap n pct
1: 0 5333 0.26665
2: 1 14667 0.73335
如何针对公司标识符中重叠的交易 ID 更改此代码?我自己做的一个改变没有产生令人满意的结果:
setkey(dt,FirmID,start,end)
foverlaps(dt,dt,by.x=c("FirmID","start","end"),by.y=c("FirmID","start","end"))[
,.(noverlap=.N),by=.(ID,row)][
,.(overlap = max(noverlap>1)),by=ID][
,.(n=.N),by=.(overlap)][
,pct:=n/sum(n)][]
overlap n pct
1: 0 5333 0.26665
2: 1 14667 0.73335
我费了好大劲才想出另一种情况的解决方案, 所以我不确定如何调整那个版本, 但我相信在这种情况下你可以通过内部 non-equi join:
获得你想要的结果dt <- data.table(df, key = c("FirmID", "ID", "start", "end"))
dt[, firm_total := .N, by = "FirmID"][
dt, .(FirmID, firm_total), on = .(FirmID, ID < ID, start <= end, end >= start), nomatch = NULL, mult = "all"][
, .(n = .N, pct = .N / (firm_total[1L] * (firm_total[1L] - 1L) / 2L)), by = "FirmID"]
我们在与 ID < ID
的连接中避免了冗余行
(请注意,此处应解释为 left-hand side column's ID < right-hand side column's ID)。
冗余可能发生,因为,
如果 ID x
与 ID y
重叠,
y
与 x
重叠。
如果你把所有的ID对放到一个矩阵中,
重叠的最大数量将是下三角中的元素数量,
可以用 n * (n - 1) / 2
计算,
这就是我们最初添加 firm_total
.
我没有进行广泛的测试,但这个版本可能更适合这种情况。
foverlaps
的文档指出它主要针对一个 table 比另一个小得多的连接,
并解释为什么它可能是一项昂贵的操作。
你正在做 self-join,
所以两个 table 大小相同。
还有一个 table.express
版本的解决方案,因为为什么不:
library(table.express)
dt %>%
group_by(FirmID) %>%
mutate(firm_total = .N) %>%
inner_join(dt, FirmID, ID < ID, start <= end, end >= start, .expr = TRUE) %>%
select(FirmID, firm_total) %>%
group_by(FirmID) %>%
summarize(n = .N, pct = .N / (firm_total[1L] * (firm_total[1L] - 1L) / 2))
编辑:如果你想要你的 overlap
列,你可以用 size of lower triangular - n
.