我的数据是动物群体中的个体随着时间的推移(个体出生,个体死亡),因此所有个体在不同的时间长度内与其他个体重叠。A列是个人身份,B列是“开始日期”,"C“列是”结束日期“。
我想创建一个表格或矩阵(后者可能更容易阅读),它显示所有成对的个体同时在组中存活/在一起的时间。我想用R做这件事。
示例数据:
ID start.date end.date
1 5/22/83 10/31/15
2 7/10/94 3/15/15
3 5/24/96 10/31/15
4 10/1/99 5/12/14示例输出(数字表示重叠的近似年份):
1 2 3 4
1 NA 21 19 15
2 NA NA 19 15
3 NA NA NA 15
4 NA NA NA NA虽然我在脑海中有一个特定的问题(动物共同居住时间),但该解决方案/方法可以用于计算任何类型重叠日期范围的二元持续时间。
一些表面上类似的工作已经指出了here,使用foverlaps函数,但是这个函数和我在其他问题中看到的所有类似问题的相关文档似乎处理涉及两个数据表的问题。无可否认,底层的概念是相似的,都是在不同的数据中找到共同的日期,但我不知道如何编写一些代码来使用foverlaps函数来解决我的问题(在一个表中,在所有可能的个体集合中查找公共范围)。我想过做一些重复的循环,但随着数据表变得越来越大,这将会很麻烦,而且会变得更加困难。
发布于 2018-07-17 13:34:58
foverlaps()不是必需的。取而代之的是,每个ID使用非等自连接相互比较(类似于combn()所做的),重叠的年份使用pmin()和pmax()计算。
library(data.table)
# add dummy ID column to join on for non-equi join
DT[, join.ID := ID][
# non-equi join to create combinations
DT, on = .(join.ID >= join.ID)][
# compute years of overlap
, overlap.years := round(as.integer(
pmin(end.date, i.end.date) - pmax(start.date, i.start.date)) / 365.25)][
# remove negative values (no overlap)
overlap.years > 0][
# reshape from long to wide format
, dcast(.SD, i.ID ~ ID)]i.ID 1 2 3 4 1: 1 32 21 19 15 2: 2 NA 21 19 15 3: 3 NA NA 19 15 4: 4 NA NA NA 15
请注意,OP的预期结果有所不同。主对角线包含每个人的年龄。我认为在比较同居时间时,这是一个有价值的信息。
数据
library(data.table)
DT <- fread(
"ID start.date end.date
1 5/22/83 10/31/15
2 7/10/94 3/15/15
3 5/24/96 10/31/15
4 10/1/99 5/12/14"
)
# convert date string to class Date
cols <- c("start.date", "end.date")
DT[, (cols) := lapply(.SD, lubridate::mdy), .SDcols = cols]多个时期的同居
如果有个人离开群,稍后返回,则需要修改以上代码:
# read dat of new case
DT2 <- fread(
"ID start.date end.date
1 5/22/83 10/31/15
2 7/10/94 3/15/15
3 5/24/96 10/31/15
4 10/1/99 5/12/14
4 3/20/15 5/12/16"
)
cols <- c("start.date", "end.date")
DT2[, (cols) := lapply(.SD, lubridate::mdy), .SDcols = cols]
DT2请注意,单个4已经离开组10个月了。
DT2[, join.ID := ID][
DT2, on = .(join.ID >= join.ID), allow = TRUE][
, overlap.years := as.integer(
pmin(end.date, i.end.date) - pmax(start.date, i.start.date)) / 365.25][
overlap.years > 0][
, dcast(.SD, i.ID ~ ID, function(x) round(sum(x), 1), fill = NA)]i.ID 1 2 3 4 1: 1 32.4 20.7 19.4 15.2 2: 2 NA 20.7 18.8 14.6 3: 3 NA NA 19.4 15.2 4: 4 NA NA NA 15.8
请注意,主对角线不再表示年龄,而是个人与群体联系的总持续时间。
https://stackoverflow.com/questions/41254106
复制相似问题