首页 > 解决方案 > R:遍历 2 列以子集 data.table 或 data.frame

问题描述

我想使用循环将 data.table 或数据框按两列进行子集化。我想知道如何使用 purrr 或 dplyr 以一种很好的方式做到这一点。

这是我的例子:

library(data.table)

# my example data
DF <- as.data.table(cbind.data.frame(x = c(100.01, 100.03, 100.09, 100.01, 233.45, 233.56, 233.51, 233.45, 561.1, 556.1, 447.23),
                    y = c(11, 10.8, 10.9, 20, 2, 2.2, 4, 6, 11, 2.1, 10.6)))

# my filter conditions
mycondition <- cbind.data.frame(c1 = c(100, 233.5), c2 = c(11, 2))

## subset DF by selecting the values in mycondition with a tolerance of 0.5
result1 <- DF[x%between%c(mycondition$c1[1] - 0.5, mycondition$c1[1] + 0.5) & y%between%c(mycondition$c2[1] - 0.5, mycondition$c2[1] + 0.5)]

result2 <- DF[x%between%c(mycondition$c1[2] - 0.5, mycondition$c1[2] + 0.5) & y%between%c(mycondition$c2[2] - 0.5, mycondition$c2[2] + 0.5)]

## combined result
result <- rbind.data.frame(result1, result2)

> result
        x    y
1: 100.01 11.0
2: 100.03 10.8
3: 100.09 10.9
4: 233.45  2.0
5: 233.56  2.2

我想知道是否有一种很好的方法可以用 R 包循环它purrrdolyr用来做它?

谢谢。

标签: rloopsdata.tablesubsetpurrr

解决方案


不需要循环,这是一个纯data.table方法。

library(data.table)
setDT(mycondition)
mycondition[, c("c1a", "c1b", "c2a", "c2b") := .(c1-0.5, c1+0.5, c2-0.5, c2+0.5)
  ][DF, on=.(c1a<=x, c1b>=x, c2a<=y, c2b>=y)
  ][!is.na(c1), .(x=c1a, y=c2a)]
#         x     y
#     <num> <num>
# 1: 100.01  11.0
# 2: 100.03  10.8
# 3: 100.09  10.9
# 4: 233.45   2.0
# 5: 233.56   2.2

仅供参考,您生成数据的代码不必要地令人费解。以下是功能等效的:

DF <- as.data.table(cbind.data.frame(x = c(100.01, 100.03, 100.09, 100.01, 233.45, 233.56, 233.51, 233.45, 561.1, 556.1, 447.23),
                    y = c(11, 10.8, 10.9, 20, 2, 2.2, 4, 6, 11, 2.1, 10.6)))
DF <- data.table(x = c(100.01, 100.03, 100.09, 100.01, 233.45, 233.56, 233.51, 233.45, 561.1, 556.1, 447.23),
                 y = c(11, 10.8, 10.9, 20, 2, 2.2, 4, 6, 11, 2.1, 10.6))

mycondition <- cbind.data.frame(c1 = c(100, 233.5), c2 = c(11, 2))
mycondition <- data.frame(c1 = c(100, 233.5), c2 = c(11, 2)) # though not a data.table, as I need above
mycondition <- data.table(c1 = c(100, 233.5), c2 = c(11, 2))

而且由于您已经在使用data.table,我建议您停止使用rbind.data.frame,因为它不像rbind.data.table, aka那样有特色(或者可能安全?) rbind(DF, ...)。也许更好的是data.table::rbindlist(list(result1, result2)),因为它有一些附加功能。


推荐阅读