仅供参考,“纬度”通常是北/南,对我来说,这通常意味着“顶部”和“底部”更有意义。该代码与您的框架相匹配,但似乎有些不同。
这是一个基于范围的连接或“非相等”连接。 dplyr 本身不支持此功能,但可以在 R 中使用至少三个其他包完成:
模糊连接
fuzzyjoin::fuzzy_left_join(
df1, df2,
by = c("lat" = "left", "lat" = "right", "lng" = "bottom", "lng" = "top"),
match_fun = list(`>=`, `<=`, `>=`, `<=`)
)[, c("lat", "lng", "id")]
# lat lng id
# 1 1 10 a
# 2 3 11 c
# 3 2 12 <NA>
(还有fuzzyjoin::fuzzy_inner_join,如果你喜欢把最下面的那一行放在这里。)
fuzzyjoin 中的“动词”函数被有意(我相信)命名为与 dplyr 连接函数一致,因此可以在 dplyr 管道中内联完成:
library(dplyr)
df1 %>%
fuzzyjoin::fuzzy_left_join(
., df2,
by = c("lat" = "left", "lat" = "right", "lng" = "bottom", "lng" = "top"),
match_fun = list(`>=`, `<=`, `>=`, `<=`)
) %>%
select(lat, lng, id)
数据表
library(data.table)
DT1 <- as.data.table(df1)
DT2 <- as.data.table(df2)
DT2[DT1, on = .(left <= lat, right >= lat, bottom <= lng, top >= lng)][, .(lat=left, lng=top, id)]
# lat lng id
# <int> <int> <char>
# 1: 1 10 a
# 2: 3 11 c
# 3: 2 12 <NA>
我应该注意,合并后的列名不一定是预期的:例如,您不会看到 lat 或 lng,因为输出列名取自合并,即DT2。 DT2[DT1,...] 的合并语法类似于left_join(DT1, DT2, ...),因此名称与预期相反。没有 data.table::[-syntax 用于内部或完全合并,也没有用于从另一个参数中获取名称。 (在我看来,左合并应该使用“左”框架中的名称,但它可能是这样的。)
sqldf
SQL 本身就支持它,因此如果您在某处使用 DBMS,则可以在那里完成查询和连接。缺少这一点,sqldf 包允许 SQL 访问本地 R 对象(使用 SQLite 引擎)。
sqldf::sqldf(
"select df1.lat, df1.lng, df2.id
from df1
left join df2 on df1.lat between df2.left and df2.right
and df1.lng between df2.bottom and df2.top"
)
# lat lng id
# 1 1 10 a
# 2 3 11 c
# 3 2 12 <NA>
数据
df1 <- structure(list(lat = c(1L, 3L, 2L), lng = 10:12), class = "data.frame", row.names = c(NA, -3L))
df2 <- structure(list(id = c("a", "b", "c"), left = c(0.5, 1.5, 2.5), right = c(1.5, 2.5, 3.5), bottom = c(9L, 9L, 10L), top = c(11L, 11L, 11L)), class = "data.frame", row.names = c(NA, -3L))