在 data.table 中按组按不同范围过滤
Filtering by different ranges by group in data.table
我在 table 中有一些数据,我想进行非等值连接(我认为这是正确的术语)并针对不同的组按不同的范围对其进行过滤。在下面的示例中,我想过滤组“a”,以便它只有 returns 介于 1 和 20(含)之间的值和组“b”,所以它只有 returns 介于 80 和 100(含)之间的值).我的阅读建议 inrange
应该是要使用的项目。我知道如何在一般情况下使用它,但我不确定如何按组将其设置为具有不同范围的 运行。 (示例代码改编自 ?inrange
)
创建示例数据
set.seed(1234)
Y = data.table(a=sample(1:100,100), val=runif(100), group=c(rep("a",50),rep("b",50)))
range = data.table(group=c("a","b"),start = c(1,80), end = c(20,100))
尝试过滤
Y[inrange(a, range$start, range$end),,by=group]
这显然不起作用,而是将这些范围应用于整个数据集并抛出错误消息 Ignoring by= because j= is not supplied
。我想我很清楚这不起作用,因为我没有在范围 table 和 Y 之间创建 'join',但我不知道如何制作两个 table s 通过 inrange
.
进行分组交流
注意:实际上 a 中的值将是 posixct 日期时间,但为了简单起见,我在这里不使用它。
也许:
Y[range, K := TRUE, on = .(group, a >= start, a <= end)][!is.na(K),]
# a val group K
# <int> <num> <char> <lgcl>
# 1: 9 0.60189755 a TRUE
# 2: 5 0.99874081 a TRUE
# 3: 16 0.55512663 a TRUE
# 4: 4 0.42944396 a TRUE
# 5: 14 0.43101637 a TRUE
# 6: 3 0.47880269 a TRUE
# 7: 2 0.02220682 a TRUE
# 8: 6 0.63891131 a TRUE
# 9: 8 0.83470266 a TRUE
# 10: 17 0.98304402 a TRUE
# 11: 98 0.76785547 b TRUE
# 12: 94 0.30766574 b TRUE
# 13: 88 0.25814665 b TRUE
# 14: 89 0.49954639 b TRUE
# 15: 83 0.50892062 b TRUE
# 16: 95 0.49443856 b TRUE
# 17: 97 0.56695890 b TRUE
# 18: 87 0.98970989 b TRUE
# 19: 82 0.53190509 b TRUE
# 20: 100 0.59662376 b TRUE
# a val group K
还有其他方法可以做到这一点,但它们涉及重命名或信息丢失。例如,
left-join range
和 Y
,我们失去 a
:
Y[range, on = .(group, a >= start, a <= end)]
# a val group a.1
# <int> <num> <char> <int>
# 1: 1 0.60189755 a 20
# 2: 1 0.99874081 a 20
# 3: 1 0.55512663 a 20
# ...
# 18: 80 0.98970989 b 100
# 19: 80 0.53190509 b 100
# 20: 80 0.59662376 b 100
# a val group a.1
修复方法是将 Y$a
复制到一个新变量中,然后加入它:
Y[,a1 := a][range, on = .(group, a1 >= start, a1 <= end)]
# a val group a1 a1.1
# <int> <num> <char> <int> <int>
# 1: 9 0.60189755 a 1 20
# 2: 5 0.99874081 a 1 20
# 3: 16 0.55512663 a 1 20
# ...
# 18: 87 0.98970989 b 80 100
# 19: 82 0.53190509 b 80 100
# 20: 100 0.59662376 b 80 100
# a val group a1 a1.1
left-join Y
和 range
,我们将 a
复制到 start
和 end
但没有明确的指示符过滤条件:
range[Y, on = .(group, start <= a, end >= a)]
# group start end val
# <char> <int> <int> <num>
# 1: a 28 28 0.85026492
# 2: a 80 80 0.23466126
# 3: a 22 22 0.98816745
# ...
# 98: b 82 82 0.53190509
# 99: b 100 100 0.59662376
# 100: b 30 30 0.26388647
# group start end val
一种补救方法是复制到另一个字段中,该字段将为我们提供我们需要能够过滤的合并指示符。但即便如此,我们也必须重命名才能重新获得 a
的数据:
range[, K := TRUE][Y, on = .(group, start <= a, end >= a)][ !is.na(K), ]
# group start end K val
# <char> <int> <int> <lgcl> <num>
# 1: a 9 9 TRUE 0.60189755
# 2: a 5 5 TRUE 0.99874081
# 3: a 16 16 TRUE 0.55512663
# ...
# 18: b 87 87 TRUE 0.98970989
# 19: b 82 82 TRUE 0.53190509
# 20: b 100 100 TRUE 0.59662376
# group start end K val
我在 table 中有一些数据,我想进行非等值连接(我认为这是正确的术语)并针对不同的组按不同的范围对其进行过滤。在下面的示例中,我想过滤组“a”,以便它只有 returns 介于 1 和 20(含)之间的值和组“b”,所以它只有 returns 介于 80 和 100(含)之间的值).我的阅读建议 inrange
应该是要使用的项目。我知道如何在一般情况下使用它,但我不确定如何按组将其设置为具有不同范围的 运行。 (示例代码改编自 ?inrange
)
创建示例数据
set.seed(1234)
Y = data.table(a=sample(1:100,100), val=runif(100), group=c(rep("a",50),rep("b",50)))
range = data.table(group=c("a","b"),start = c(1,80), end = c(20,100))
尝试过滤
Y[inrange(a, range$start, range$end),,by=group]
这显然不起作用,而是将这些范围应用于整个数据集并抛出错误消息 Ignoring by= because j= is not supplied
。我想我很清楚这不起作用,因为我没有在范围 table 和 Y 之间创建 'join',但我不知道如何制作两个 table s 通过 inrange
.
注意:实际上 a 中的值将是 posixct 日期时间,但为了简单起见,我在这里不使用它。
也许:
Y[range, K := TRUE, on = .(group, a >= start, a <= end)][!is.na(K),]
# a val group K
# <int> <num> <char> <lgcl>
# 1: 9 0.60189755 a TRUE
# 2: 5 0.99874081 a TRUE
# 3: 16 0.55512663 a TRUE
# 4: 4 0.42944396 a TRUE
# 5: 14 0.43101637 a TRUE
# 6: 3 0.47880269 a TRUE
# 7: 2 0.02220682 a TRUE
# 8: 6 0.63891131 a TRUE
# 9: 8 0.83470266 a TRUE
# 10: 17 0.98304402 a TRUE
# 11: 98 0.76785547 b TRUE
# 12: 94 0.30766574 b TRUE
# 13: 88 0.25814665 b TRUE
# 14: 89 0.49954639 b TRUE
# 15: 83 0.50892062 b TRUE
# 16: 95 0.49443856 b TRUE
# 17: 97 0.56695890 b TRUE
# 18: 87 0.98970989 b TRUE
# 19: 82 0.53190509 b TRUE
# 20: 100 0.59662376 b TRUE
# a val group K
还有其他方法可以做到这一点,但它们涉及重命名或信息丢失。例如,
left-join
range
和Y
,我们失去a
:Y[range, on = .(group, a >= start, a <= end)] # a val group a.1 # <int> <num> <char> <int> # 1: 1 0.60189755 a 20 # 2: 1 0.99874081 a 20 # 3: 1 0.55512663 a 20 # ... # 18: 80 0.98970989 b 100 # 19: 80 0.53190509 b 100 # 20: 80 0.59662376 b 100 # a val group a.1
修复方法是将
Y$a
复制到一个新变量中,然后加入它:Y[,a1 := a][range, on = .(group, a1 >= start, a1 <= end)] # a val group a1 a1.1 # <int> <num> <char> <int> <int> # 1: 9 0.60189755 a 1 20 # 2: 5 0.99874081 a 1 20 # 3: 16 0.55512663 a 1 20 # ... # 18: 87 0.98970989 b 80 100 # 19: 82 0.53190509 b 80 100 # 20: 100 0.59662376 b 80 100 # a val group a1 a1.1
left-join
Y
和range
,我们将a
复制到start
和end
但没有明确的指示符过滤条件:range[Y, on = .(group, start <= a, end >= a)] # group start end val # <char> <int> <int> <num> # 1: a 28 28 0.85026492 # 2: a 80 80 0.23466126 # 3: a 22 22 0.98816745 # ... # 98: b 82 82 0.53190509 # 99: b 100 100 0.59662376 # 100: b 30 30 0.26388647 # group start end val
一种补救方法是复制到另一个字段中,该字段将为我们提供我们需要能够过滤的合并指示符。但即便如此,我们也必须重命名才能重新获得
a
的数据:range[, K := TRUE][Y, on = .(group, start <= a, end >= a)][ !is.na(K), ] # group start end K val # <char> <int> <int> <lgcl> <num> # 1: a 9 9 TRUE 0.60189755 # 2: a 5 5 TRUE 0.99874081 # 3: a 16 16 TRUE 0.55512663 # ... # 18: b 87 87 TRUE 0.98970989 # 19: b 82 82 TRUE 0.53190509 # 20: b 100 100 TRUE 0.59662376 # group start end K val