r - 如何过滤掉数据表中的坐标(纬度,纬度)?



TL;博士

这张左外连接的图像准确地描绘了我想要的:根据与另一data.tablelat, lon列完全匹配的两列lat, lon删除data.table

问题所在

假设我有以下data.table"dt.master",其中包含超过 100 万行,其中包含某个位置lat, lonid和坐标:

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
...   ...      ...  

尽管看起来很简单,但我无法正确处理。

到目前为止我做了什么

  • 使用merge,如下所示:

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

    但这会产生匹配的行,因此是内部连接。我想过通过使用subset根据此结果删除行:

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

    但问题是它部分有效,因为上面示例中只删除了 1 行,而不是我想要的 2 行。不知何故,它只删除了第一个"命中"。

  • 使用快速且脏的解决方案,方法是将lat, lon连接到两个数据表中名为"C"的新列,然后将其删除:

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

    然而,当两行中只有 1 行被删除时,会出现同样的问题。

我想你正在寻找这个:

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

我们可以使用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

最新更新