检查数据框中的值是否有条件地位于另一个数据框的两列指定的值范围之间
Check if a value in a dataframe is conditionally between a range of values specified by two columns of another dataframe
所以,我有两个 dataframes
- 有点大(df1 ~= 20k 行 & df2 ~= 150 万) - 我想检查 df1
中的值是否介于 df2$low & df2$high
,但有条件地执行(以限制检查次数)并且仅在 abs(df1$val-df2$val) < 2
时才执行检查。如果发现 df1 中的值在 df2 范围内,则添加到具有 TRUE/FALSE
个值的新列中。
df1
weight
low
high
94.99610
94.99608
94.99613
95.00561
95.00558
95.00566
df2
index
th_weight
1
94.996092
2
95.496336
3
95.509906
4
97.473292
5
100.519060
期望的输出应该是:
df1
weight
lower
upper
filter
94.99610
94.99608
94.99613
TRUE
95.00561
95.00558
95.00566
FALSE
因此在该示例中,逻辑是 df2
中的第 4 行和第 5 行将被省略。 df2
的第 1 行中的值在 df1$low & df1$high
的第 1 行内,因此 df1[,filter := TRUE]
对于该权重
我尝试了多种方法,双循环进入 data.table
,正如预期的那样,这是效率最低的,我还尝试用 [=21] 制作 df1 x df2
的笛卡尔积=] 但那里有内存问题。即使拆分成块并附加到文件中(这样我以后可以通过 UNIX sed
或 awk
轻松操作文件)也没有帮助。
可能有一个非常简单的方法来做到这一点,我可能完全偏离了轨道,所以我提前道歉。
使用 non-equi 与 data.table
连接 - 将第一个数据转换为 data.table (setDT
),创建 filter
列作为逻辑列 (FALSE
) 值。执行 non-equi 连接,并将 filter
分配 (:=
) 到 TRUE
,这仅在条件 ( abs(weight - th_weight) < 2
) 遇见
library(data.table)
setDT(df1)[, filter := FALSE]
df1[df2, filter := abs(weight - th_weight) < 2,
on = .(low <= th_weight, high >= th_weight)]
-输出
> df1
weight low high filter
<num> <num> <num> <lgcl>
1: 94.99610 94.99608 94.99613 TRUE
2: 95.00561 95.00558 95.00566 FALSE
数据
df1 <- structure(list(weight = c(94.9961, 95.00561), low = c(94.99608,
95.00558), high = c(94.99613, 95.00566)), class = "data.frame", row.names = c(NA,
-2L))
df2 <- structure(list(index = 1:5, th_weight = c(94.996092, 95.496336,
95.509906, 97.473292, 100.51906)), class = "data.frame", row.names = c(NA,
-5L))
所以,我有两个 dataframes
- 有点大(df1 ~= 20k 行 & df2 ~= 150 万) - 我想检查 df1
中的值是否介于 df2$low & df2$high
,但有条件地执行(以限制检查次数)并且仅在 abs(df1$val-df2$val) < 2
时才执行检查。如果发现 df1 中的值在 df2 范围内,则添加到具有 TRUE/FALSE
个值的新列中。
df1
weight | low | high |
---|---|---|
94.99610 | 94.99608 | 94.99613 |
95.00561 | 95.00558 | 95.00566 |
df2
index | th_weight |
---|---|
1 | 94.996092 |
2 | 95.496336 |
3 | 95.509906 |
4 | 97.473292 |
5 | 100.519060 |
期望的输出应该是:
df1
weight | lower | upper | filter |
---|---|---|---|
94.99610 | 94.99608 | 94.99613 | TRUE |
95.00561 | 95.00558 | 95.00566 | FALSE |
因此在该示例中,逻辑是 df2
中的第 4 行和第 5 行将被省略。 df2
的第 1 行中的值在 df1$low & df1$high
的第 1 行内,因此 df1[,filter := TRUE]
对于该权重
我尝试了多种方法,双循环进入 data.table
,正如预期的那样,这是效率最低的,我还尝试用 [=21] 制作 df1 x df2
的笛卡尔积=] 但那里有内存问题。即使拆分成块并附加到文件中(这样我以后可以通过 UNIX sed
或 awk
轻松操作文件)也没有帮助。
可能有一个非常简单的方法来做到这一点,我可能完全偏离了轨道,所以我提前道歉。
使用 non-equi 与 data.table
连接 - 将第一个数据转换为 data.table (setDT
),创建 filter
列作为逻辑列 (FALSE
) 值。执行 non-equi 连接,并将 filter
分配 (:=
) 到 TRUE
,这仅在条件 ( abs(weight - th_weight) < 2
) 遇见
library(data.table)
setDT(df1)[, filter := FALSE]
df1[df2, filter := abs(weight - th_weight) < 2,
on = .(low <= th_weight, high >= th_weight)]
-输出
> df1
weight low high filter
<num> <num> <num> <lgcl>
1: 94.99610 94.99608 94.99613 TRUE
2: 95.00561 95.00558 95.00566 FALSE
数据
df1 <- structure(list(weight = c(94.9961, 95.00561), low = c(94.99608,
95.00558), high = c(94.99613, 95.00566)), class = "data.frame", row.names = c(NA,
-2L))
df2 <- structure(list(index = 1:5, th_weight = c(94.996092, 95.496336,
95.509906, 97.473292, 100.51906)), class = "data.frame", row.names = c(NA,
-5L))