R:根据其他数据框的值添加索引列
R: Add index column based on values from other dataframe
我正在尝试给坐标值一个标签。
我有一个带坐标的数据框,看起来类似于
lat lng
1 10
3 11
2 12
我还有一个格子的上下左右坐标数据
id left right bottom top
a 0.5 1.5 9 11
b 1.5 2.5 9 11
c 2.5 3.5 10 11
id 列是每个矩形网格的 id。
我想根据网格的经纬度范围将id合并到第一个dataframe。
所以预期输出的第一行应该是这样的
lat lng id
1 10 a
如果不一一指定范围,我将如何实现。我在考虑某种子集函数,但我不确定如何编写它。
非常感谢您的帮助。
仅供参考,“纬度”通常是 North/South,对我来说通常意味着“顶部”和“底部”会更有意义。该代码与您的框架匹配,但似乎有点不同。
这是基于范围的联接或“非等值”联接。这在 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)
data.table
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>
我应该注意,列名 post-merge 不一定是人们所期望的:例如,您不会看到 lat
或 lng
,因为输出列名取自合并的“右侧”,即 DT2
。 DT2[DT1,...]
的合并语法类似于 left_join(DT1, DT2, ...)
,因此名称与人们可能期望的相反。没有用于内部或完全合并的 data.table::[
语法,也没有用于从另一个参数中获取名称的语法。 (在我看来,左合并应该使用“左”框架中的名称,但可能有充分的理由这样做。)
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))
我正在尝试给坐标值一个标签。
我有一个带坐标的数据框,看起来类似于
lat lng
1 10
3 11
2 12
我还有一个格子的上下左右坐标数据
id left right bottom top
a 0.5 1.5 9 11
b 1.5 2.5 9 11
c 2.5 3.5 10 11
id 列是每个矩形网格的 id。
我想根据网格的经纬度范围将id合并到第一个dataframe。
所以预期输出的第一行应该是这样的
lat lng id
1 10 a
如果不一一指定范围,我将如何实现。我在考虑某种子集函数,但我不确定如何编写它。
非常感谢您的帮助。
仅供参考,“纬度”通常是 North/South,对我来说通常意味着“顶部”和“底部”会更有意义。该代码与您的框架匹配,但似乎有点不同。
这是基于范围的联接或“非等值”联接。这在 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)
data.table
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>
我应该注意,列名 post-merge 不一定是人们所期望的:例如,您不会看到 lat
或 lng
,因为输出列名取自合并的“右侧”,即 DT2
。 DT2[DT1,...]
的合并语法类似于 left_join(DT1, DT2, ...)
,因此名称与人们可能期望的相反。没有用于内部或完全合并的 data.table::[
语法,也没有用于从另一个参数中获取名称的语法。 (在我看来,左合并应该使用“左”框架中的名称,但可能有充分的理由这样做。)
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))