【发布时间】:2016-05-15 14:44:29
【问题描述】:
我想根据两个条件聚合一个data.table,其中一个附加到另一行。这是我的问题和一个可重现的例子:
我有一对起点-终点。 对于每个起点,我想对给定condition1 的目的地中的积分求和。但是,有两个棘手的问题。
- 每个起点-终点对中的点只能求和一次
- 只有当
condition2在反向通量 中得到满足时,才能对分数进行总结。也就是说,A-B中的点只能在condition1==T和如果有B-A对其中condition2==T时相加
可重现的例子:
library(data.table)
dt <- data.table( origin = c("A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "C", "C", "B", "B", "B", "B", "B", "C", "C", "B", "A", "C", "C", "C", "C", "C", "A", "A", "C", "C", "B", "B"),
destination = c("A", "A", "A", "A", "B", "B", "A", "A", "C", "C", "A", "A", "B", "B", "B", "C", "C", "B", "B", "A", "B", "C", "C", "C", "A", "A", "C", "C", "B", "B", "C", "C"),
points_in_dest = c(5, 5, 5, 5, 4, 4, 5, 5, 3, 3, 5, 5, 4, 4, 4, 3, 3, 4, 4, 5, 4, 3, 3, 3, 5,5, 3, 3, 4, 4, 3, 3),
depart_time = c(7, 8, 16, 18, 7, 8, 16, 18, 7, 8, 16, 18, 7, 8, 16, 7, 8, 16, 18, 8, 16, 7, 8, 18, 7, 8, 16, 18, 7, 8, 16, 18),
travel_time = c(0, 0, 0, 0, 70, 10, 70, 10, 10, 10, 70, 70, 0, 0, 0, 70, 10, 10, 70, 70, 10, 0, 0, 0, 10, 70, 10, 70, 10, 70, 70, 10) )
dt[ depart_time<=8 & travel_time < 60, condition1 := T] # condition 1 - trips must be in the morning and shorter than 60 min
dt[ depart_time>=16 & travel_time < 60, condition2 := T] # condition 2 - trips must be in the afternoon and shorter than 60 min
如果我只考虑condition1 来总结积分,这就是我得到的。注意这个查询没有处理两个问题:(1)当有多个满足condition1的起点-目的地对时,它是重复计算点,(2)当condition2不满足时,它不排除点
dt[ condition1==T, .(poits = sum(points_in_dest)), by=.(origin)]
> origin poits
> 1: A 20
> 2: B 11
> 3: C 15
期望的输出
> origin poits
> 1: A 9
> 2: B 7
> 3: C 12
我的真实数据框约为 8000 万行,因此我希望有一个有效的解决方案,可能基于 data.table。我意识到这是一个棘手的问题,我将不胜感激。提前致谢
背景
这是具有时空限制的可访问性时间地理中的常见问题。问题是,例如,考虑到您的时空限制以及您住在 A 区,您可以选择多少工作机会。 A区有5个工作,B区有4个工作,C区有3个工作,你有资格在所有这些工作。但是,只有在早上可以到办公室 (condition1) 并且可以在下午 4 点之后回到家 (condition2) 的情况下,您才能在工作岗位上工作。
【问题讨论】:
-
那么
depart_time <= 8条件从何而来?我没有看到它在任何地方指定。还是只是为了说明?即,在您的示例中,您只想要前两行? -
@DavidArenburg,你说得对,我应该提到
depart_time条件,我只想对第一行求和。但请记住,我的真实数据框有更多的起点-目的地和出发时间对,为了简单起见,这里的示例只是部分子集 -
会在您的数据集上使用以下内容吗?
res <- dt[condition2 == 1L, dt[condition1 == 1L & depart_time < 8][.SD, on = c(destination = "origin", origin = "destination")]] ; res[, .(points = sum(points_in_dest, na.rm = TRUE)), by = origin]。这应该很快,但我不确定我是否完全理解你的问题。或者这个dt[dt[condition2 == 1L], on = c(destination = "origin", origin = "destination"), sum(points_in_dest[depart_time < 8]), by = origin] -
@DavidArenburg,感谢您的回答。我认为它与我想要的非常接近,但它在我的数据中不起作用,因为它具有更多条件 1 和 2 的组合,因此我更新了问题中提供的示例数据以涵盖所有可能的组合。跨度>
标签: r dataframe data.table aggregate