【问题标题】:R - Relational Operators and VectorizationR - 关系运算符和向量化
【发布时间】:2016-09-18 02:03:18
【问题描述】:

当人们扫描徽章时,我有一个向量。我还有另一组时间是“测量点”。

scans = structure(c(1388570120, 1388572119, 1388575229, 1388577402, 1388580457, 1388583364, 1388586817, 1388589929, 1388593054, 1388599025), class = c("POSIXct", "POSIXt"), tzone = "UTC")
points = as.POSIXct(9*3600,"UTC",origin="2014-01-01")+seq(0,10*3600,3600)

我想要做的是计算有多少scans 大于(或等于)points

sum(scans >= points[1])
#> [1] 10

这一次可以工作一个,并且可以很容易地转换为 for 循环或 lapply

lapply(points,function(x){sum(scans >= x)})

但是,我不能简单地使用 scans >= points 并返回一个列表,其中所有扫描都与逐个元素的点进行比较。

R 中有没有一种方法可以在不使用循环结构的情况下将一个完整的向量与另一个向量的每个元素进行比较(因此结果与上面的 lapply 示例相同,但可能在结构上除外)? 我实际上有一个扫描向量列表,我已经通过lapplying,我希望有一种方法可以避免 R 中的嵌套循环。

【问题讨论】:

  • 看看能不能用?findInterval;至少在这个例子中,见length(scans) - findInterval(points, scans)
  • @alexis_laz 有趣的功能,我得玩一下。

标签: r vector vectorization


【解决方案1】:

你可以的

colSums(outer(scans,points,'>='))

但我不能保证中间矩阵会适合内存。

【讨论】:

  • 这太棒了!在我的机器上获得相同结果的速度比 lapply 快约 5 倍。
【解决方案2】:

您可以使用data.tabledevelopment version 执行以下操作:

library(data.table)
dt1 = data.table(scans)
dt2 = data.table(points)

dt1[dt2, on = .(scans >= points), .N, by = .EACHI]
#                  scans  N
# 1: 2014-01-01 09:00:00 10
# 2: 2014-01-01 10:00:00  9
# 3: 2014-01-01 11:00:00  8
# 4: 2014-01-01 12:00:00  6
# 5: 2014-01-01 13:00:00  5
# 6: 2014-01-01 14:00:00  4
# 7: 2014-01-01 15:00:00  3
# 8: 2014-01-01 16:00:00  2
# 9: 2014-01-01 17:00:00  1
#10: 2014-01-01 18:00:00  0
#11: 2014-01-01 19:00:00  0

这应该比构建完整的外部产品更节省内存。

【讨论】:

  • 如果我有 2 次扫描(进入和退出)并想检查 points 是否介于两者之间,我可以这样做吗?我知道如何扩展其他答案。
  • .EACHI 仍然需要做一些工作才能适用于所有情况,但对于这种情况,您可以像dt1[dt2, on = .(scan.start <= points, scan.end > points), .N, by = .EACHI] 那样做。它还不适用于所有情况,但如果它具有一些良好的排序属性,它可能适合您的情况。如果它不起作用,您仍然可以这样做,方法是将索引添加到dt2,并在加入后按它进行分组。
猜你喜欢
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多