R:在XY网格中查找缺失的组合

Mar*_*rio 3 r matrix dataframe data.table

我有一个由X和Y坐标组成的大网格,每个坐标代表一个值。但是,网格内的某些组合不存在,请参见附图:缺少组合的网格

我想用R脚本识别缺少的xy组合,但是不知道该怎么做。获得这些组合的有效方法是什么?

我的数据示例:

df1 <- structure(list(coord_n = c(1065125L, 1065875L, 1064625L, 1064375L, 
    1065625L, 1065375L, 1065625L, 1065125L, 1065625L, 1065125L, 1066125L, 
    1064625L, 1066375L, 1064125L, 1064375L, 1064625L, 1066375L, 1064875L, 
    1066125L, 1066625L, 1064375L, 1065125L, 1066375L, 1066625L, 1065125L, 
    1065875L, 1064125L, 1064375L, 1064125L, 1065875L, 1064625L, 1065125L, 
    1065125L, 1065625L, 1066375L, 1064375L, 1064875L, 1065875L, 1066375L, 
    1066625L, 1064375L, 1064625L, 1066375L, 1065875L, 1065375L, 1065375L, 
    1066625L, 1065375L, 1064625L, 1066625L, 1066125L, 1065625L, 1065375L, 
    1065875L, 1064125L, 1064375L, 1064875L, 1065625L, 1065625L, 1064625L, 
    1064875L, 1065375L, 1065875L, 1065875L, 1066625L, 1065875L, 1064875L, 
    1066625L, 1064875L, 1064125L, 1066125L, 1064375L, 1066375L, 1064125L, 
    1066625L, 1065125L, 1064625L, 1065625L, 1066125L, 1064125L, 1066375L, 
    1066625L, 1066375L, 1064125L, 1064875L, 1065375L, 1064375L, 1065625L, 
    1065875L, 1065375L, 1066375L, 1064875L, 1064375L, 1066625L, 1064375L, 
    1065875L, 1064375L, 1065375L, 1064875L, 1066375L), coord_e = c(2418625L, 
    2419125L, 2421875L, 2418125L, 2421375L, 2422375L, 2421125L, 2418875L, 
    2418625L, 2420375L, 2419375L, 2420625L, 2418875L, 2420625L, 2419125L, 
    2420875L, 2419125L, 2419875L, 2418375L, 2421625L, 2422375L, 2422375L, 
    2422125L, 2422125L, 2420125L, 2421875L, 2421875L, 2420125L, 2422375L, 
    2420625L, 2419625L, 2418375L, 2419625L, 2418375L, 2419875L, 2420875L, 
    2421375L, 2422375L, 2422375L, 2418125L, 2418375L, 2419125L, 2418625L, 
    2418875L, 2419375L, 2421375L, 2421125L, 2419125L, 2418375L, 2419625L, 
    2418875L, 2420125L, 2419875L, 2420375L, 2420375L, 2419875L, 2420375L, 
    2422375L, 2421875L, 2422375L, 2419375L, 2420875L, 2421125L, 2421375L, 
    2419125L, 2419375L, 2421625L, 2418375L, 2418875L, 2418375L, 2420125L, 
    2419625L, 2418375L, 2420125L, 2421375L, 2422125L, 2419875L, 2420375L, 
    2420375L, 2418625L, 2421125L, 2420125L, 2421625L, 2419875L, 2419125L, 
    2420625L, 2418625L, 2419375L, 2420125L, 2418125L, 2420125L, 2418625L, 
    2418875L, 2418625L, 2421125L, 2419875L, 2421375L, 2418875L, 2420875L, 
    2421875L), density_value = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), percentage_free = c(100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
    100, 100, 100, 100, 100, 100, 100, 100)), class = c("data.table", 
    "data.frame"), row.names = c(NA, -100L))
Run Code Online (Sandbox Code Playgroud)

r2e*_*ans 5

假设每个唯一的coord_ncoord_e是可行的,这种方法发现在原始数据中未找到的唯一值的每一个组合。

allpossible <- do.call(CJ, lapply(df1[, c("coord_n", "coord_e")], unique))
allpossible
#      coord_n coord_e
#   1: 1064125 2418125
#   2: 1064125 2418375
#   3: 1064125 2418625
#   4: 1064125 2418875
#   5: 1064125 2419125
#  ---                
# 194: 1066625 2421375
# 195: 1066625 2421625
# 196: 1066625 2421875
# 197: 1066625 2422125
# 198: 1066625 2422375
Run Code Online (Sandbox Code Playgroud)

我们将采用所有可能的组合,并对原始数据进行反联接

print(allpossible[!df1, on = c("coord_n", "coord_e")], nrows = 10)
#     coord_n coord_e
#  1: 1064125 2418125
#  2: 1064125 2418875
#  3: 1064125 2419125
#  4: 1064125 2419375
#  5: 1064125 2419625
# ---                
# 94: 1066625 2420375
# 95: 1066625 2420625
# 96: 1066625 2420875
# 97: 1066625 2421875
# 98: 1066625 2422375
Run Code Online (Sandbox Code Playgroud)

演示它的工作原理:

数据按原样绘制的图(左),红色的“缺失”点(右):

library(ggplot2)
ggplot(df1, aes(coord_n, coord_e)) +
  coord_quickmap() + geom_point()
ggplot(df1, aes(coord_n, coord_e)) +
  coord_quickmap() + geom_point() +
  geom_point(data = allpossible[!df1, on = c("coord_n", "coord_e")],
             shape = 1, color = "red", size = 3)
Run Code Online (Sandbox Code Playgroud)

突出显示原始数据和缺失数据

(如果其中allpossible不应该有任何东西,我们将其视为围绕黑点的红色圆圈:演示不正确的情节


M--*_*M-- 5

这是使用dplyrtidyr获取丢失的“像素”的另一种方法:

library(dplyr)
library(tidyr)

df1 %>% 
  expand(coord_n = seq(min(df1$coord_n), max(df1$coord_n), 250), 
         coord_e = seq(min(df1$coord_e), max(df1$coord_e), 250)) %>% 
  anti_join(.,df1)

#> Joining, by = c("coord_n", "coord_e")
#> # A tibble: 98 x 2
#>    coord_n coord_e
#>      <dbl>   <dbl>
#>  1 1064125 2418125
#>  2 1064125 2418875
#>  3 1064125 2419125
#>  4 1064125 2419375
#>  5 1064125 2419625
#>  6 1064125 2420875
#>  7 1064125 2421125
#>  8 1064125 2421375
#>  9 1064125 2421625
#> 10 1064125 2422125
#> # ... with 88 more rows
Run Code Online (Sandbox Code Playgroud)

或者参考坦率的回答data.table

missingDT <- function(DT, cols, defs = NULL){
  require(data.table)
  mDT = do.call(CJ, c(DT[, ..cols], list(unique=TRUE)))
  res = DT[mDT, on=names(mDT)]
  if (length(defs)) 
    res[, names(defs) := Map(replace, .SD, lapply(.SD, is.na), defs), .SDcols=names(defs)]
  res[!complete.cases(res), cols, with=FALSE]
} 

missingDT(setDT(df1), cols = c("coord_n", "coord_e"))

#     coord_n coord_e
# 1:  1064125 2418125
# 2:  1064125 2418875
# 3:  1064125 2419125
# 4:  1064125 2419375
# 5:  1064125 2419625
# ---
# 94: 1066625 2420375
# 95: 1066625 2420625
# 96: 1066625 2420875
# 97: 1066625 2421875
# 98: 1066625 2422375
#     coord_n coord_e
Run Code Online (Sandbox Code Playgroud)