如何在data.table中过滤坐标(纬度,经度)?

3

简介

这个图像清晰地描述了左连接的过程:基于两列lat, lon,从一个data.table中删除行,这些行恰好匹配另一个data.table中的lat, lon

问题描述

假设我有一个名为"dt.master"data.table,它包含100万行数据,每行数据包括一个id和该位置的坐标lat, lon

id    lat      lon
1     43.23    5.43
2     43.56    4.12
3     52.14   -9.85
4     43.56    4.12
5     43.83    9.43
...   ...      ...

我希望做的是删除与特定坐标成对的行。您可以将这对坐标想象为被列入黑名单的(即名为"dt.blacklist"data.table):

lat      lon
43.56    4.12
11.14   -5.85

在这种情况下,当应用黑名单时,答案必须是:
id    lat      lon
1     43.23    5.43
3     52.14   -9.85
5     43.83    9.43
...   ...      ...  

尽管看起来很简单,但我还是做不对。

我到目前为止做了什么

  • Using merge, like such:

    dt.result <- merge(dt.master, dt.blacklist[, c("lat", "lon")], by.x=c("lat", "lon"), by.y=c("lat", "lon"))
    

    But that yields the rows that match and is thus an inner join. I thought about removing rows based on this result by using subset:

    subset(dt.master, lat != dt.result$lat & lon != dt.result$lon)
    

    But the issue is that it partially works as then only 1 row in the above example is removed and not 2 rows as I would like. Somehow it only removes the first "hit".

  • Using a quick and dirty solution by concatenating lat, lon to a new column named "C" in both data tables and then removing it as such:

    dt.master[C != dt.blacklist$C]
    

    Yet, the same issue arises where only 1 of the two rows is removed.


由于这些是浮点数,请检查数字是否匹配。 - akrun
2个回答

4
我想你正在寻找这个:
dt.master[!dt.blacklist, on = .(lat,lon)]

输出结果:
   id   lat   lon
1:  1 43.23  5.43
2:  3 52.14 -9.85
3:  5 43.83  9.43

由于那位绿色聪明的家伙的警告,连接浮点数可能会产生意想不到的副作用。通过转换为整数,您可以防止这种情况发生。结果,连接看起来会更加复杂:

dt.master[, (2:3) := lapply(.SD,function(x) as.integer(x*100)), .SDcols = 2:3
          ][!dt.blacklist[, (1:2) := lapply(.SD,function(x) as.integer(x*100))], on = .(lat,lon)
            ][, (2:3) := lapply(.SD, `/`, 100), .SDcols = 2:3][]

输出结果相同:
   id   lat   lon
1:  1 43.23  5.43
2:  3 52.14 -9.85
3:  5 43.83  9.43

1
被称为反连接。 - SymbolixAU
我会非常谨慎地在浮点数上进行连接操作...也许将这些坐标转换为整数(例如43.23-->4323),然后再进行连接会更好... - digEmAll
1
@digEmAll 非常感谢,已更新答案以解决该问题。 - h3rm4n
太好了,这个有效,谢谢! - dkreeft

2
我们可以使用来自data.table的fsetdiff。
fsetdiff(df1[,-1], df2)

或者可以使用dplyr中的anti_join

library(dplyr)
anti_join(df1, df2)
#  id   lat   lon
#1  1 43.23  5.43
#2  3 52.14 -9.85
#3  5 43.83  9.43

感谢您提供简单的解决方案! - dkreeft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接