首页 > 解决方案 > 如何删除行间差异小于特定值的观察值

问题描述

我有一个 data.table 由几个组(更具体的分层面板/经度数据集)组成,组中的一个单元格看起来像这样

z <- data.table(x = c(10, 10.5, 11.1, 14, 14.2, 14.4, 14.6, 17, 17.4, 30), 
            t = as.Date(c(27, 32:34, 36:41))) 
# that is:
#        x          t
#  1: 10.0 1970-01-28
#  2: 10.5 1970-02-02
#  3: 11.1 1970-02-03
#  4: 14.0 1970-02-04
#  5: 14.2 1970-02-06 # to be removed since 14.2-14.0 = 0.2 <0.5
#  6: 14.4 1970-02-07 # to be removed since 14.4-14.2 = 0.2 <0.5 and 14.4-14.0 = 0.4 <0.5
#  7: 14.6 1970-02-08 # shall NOT be removed because 14.6-14.0 = 0.6 > 0.5
#  8: 17.0 1970-02-09
#  9: 17.4 1970-02-10 # to be removed
# 10: 30.0 1970-02-11

为简单起见,这些组被排除在外,因此只需假设数据中只有两个变量(列):

我需要删除附近任何两行之间的行间差异小于 0.5 的观察结果,所以我需要这样

#        x          t
#  1: 10.0 1970-01-31
#  2: 10.5 1970-02-02
#  3: 11.1 1970-02-03
#  4: 14.0 1970-02-04
#  7: 14.6 1970-02-08
#  8: 17.0 1970-02-09
# 10: 30.0 1970-02-11

最后满足neighbor中任意两个值在变量t的阶数上相差不小于0.5。

像这样的 data.table 是否有可能,但要大得多,有几个组和近 1 亿个观察值。

提前谢谢你!

标签: rdata.table

解决方案


如果我理解正确,你可以这样做:

library(data.table)

z <- z[, filt := min(x), by = cumsum(c(1, +(x >= shift(x) + 0.5)[-1]))][
  , filt := ifelse(x == filt, 
                   shift(x, fill = x[1]), 
                   filt)][
                     x - filt >= 0.5 | x == filt, ][, filt := NULL]

解释:

  • 首先我们计算x每组的最小值;
  • 组由 创建cumsum(c(1, +(x >= shift(x) + 0.5)[-1]))。其中,我们检查每一行是否x >= shift(x) + 0.5(与前一行之间的差异x大于或等于 0.5)。这将评估为TRUE或我们用符号FALSE转向 1 和 0 ;+由于第一行将始终存在NA(因为没有前一行),我们[-1]在表达式之后删除它。由于这意味着向量中将缺少第一个值,因此我们构造另一个以 1 开头的值,然后是我们之前计算的值。之后我们应用cumsum- 后者在每次有新行大于或等于前一行 + 0.5 时分配一个值;如果中间没有这样的行,它继续分配最后一个数字(因为我们已经插入 1 作为向量的开头,它将从 1 开始,每次遇到满足条件的行时增加 +1不排除);
  • 每个先前创建的组将有只有 1 行的行;在这种情况下,我们需要交叉检查与前一行的差异。在所有其他情况下,我们交叉检查与组的第一行的差异(即根据标准不应删除的最后一行,因为它大于前一个 + 0.5);
  • 之后,我们只删除那些不满足条件的行加上我们保留等于自身的行(将始终是第一个);我们在最后删除过滤变量。

输出:

      x          t
1: 10.0 1970-01-28
2: 10.5 1970-02-02
3: 11.1 1970-02-03
4: 14.0 1970-02-04
5: 14.6 1970-02-08
6: 17.0 1970-02-09
7: 30.0 1970-02-11

推荐阅读