【问题标题】:R: Add index column based on values from other dataframeR:根据来自其他数据框的值添加索引列
【发布时间】:2021-06-17 04:06:13
【问题描述】:

我正在尝试给坐标值一个标签。

我有一个带有坐标的数据框,看起来类似于

   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 合并到第一个数据帧。

所以预期输出的第一行应该是这样的

   lat               lng       id
    1                 10        a
    

如果不一一指定范围,我将如何实现这一点。我正在考虑某种子集函数,但我不确定如何编写代码。

我将不胜感激。

【问题讨论】:

  • @akrun 抱歉提供错误信息。左右代表最大、最小纬度,底部、顶部代表矩形网格的最大、最小经度。
  • @akrun 在第二个数据中,标记为“a”的区域将有四个坐标 (0.5,9) ,(0.5,11) , (1.5,9) (1.5,11)。我想检查第一个数据中的坐标是否属于区域“a”的区域

标签: r dplyr merge subset


【解决方案1】:

仅供参考,“纬度”通常是北/南,对我来说,这通常意味着“顶部”和“底部”更有意义。该代码与您的框架相匹配,但似乎有些不同。

这是一个基于范围的连接或“非相等”连接。 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>

我应该注意,合并后的列名不一定是预期的:例如,您不会看到 latlng,因为输出列名取自合并,即DT2DT2[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))

【讨论】:

  • 非常感谢您的简短解释。衷心感谢您的努力,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多