如何根据点是否在多边形内来标记点

时间:2018-05-02 22:06:09

标签: r ggplot2 maps

我在新西兰观察鸟类的经度和纬度,存储在Count.df,变量countlongitudelatitude下。然而,其中一些出现在海上/海洋中(这是公民科学数据集)。

我想基于这些点是否超出maps::map("nz")中给出的信息来分配这些点,原因有两个:

  1. 我想在地图上绘制这些离岸点,也许使用不同的颜色
  2. 为了进一步分析,我可能会从数据集中删除它们。
  3. 如何在Count.df中根据它们是否属于由map("nz")描述的组(1:3)内部/外部创建一个新变量,该变量保存为“nzmap.dat”?

    谢谢,请尽量保持编码术语的简单。

    Count.df的子集,我有超过17000个观察值,这里是10.请注意,“count”的值对此问题没有意义。

    df <- readr::read_table2(
      "count longitude latitude
    3 174.7889 -41.24632
    1 174.7764 -41.25923
    4 176.8865 -39.67894
    1 174.7656 -36.38182
    2 175.5458 -37.13479
    2 175.5458 -37.13479
    1 176.8862 -39.67853
    1 170.6101 -45.84626
    5 174.9162 -41.25709
    2 176.8506 -39.51831"
    )
    

2 个答案:

答案 0 :(得分:3)

不幸的是,使用maps数据来空间过滤点是相当困难的,因为数据实际上是用于绘图而不是用于进行空间操作。幸运的是,使用sf包来进行这种空间工作相当容易。

  1. 首先,我从rnaturalearth包裹获得新西兰边界,这是一个方便的国家边界来源。我做了一些转换,只保留shapefile中最大的三个多边形,因为否则我们会绘制很多可能与此地图无关的远处岛屿。
  2. 然后我在新西兰附近产生一些随机点。你可以看到tibble只是一列经度和一列纬度。我们将其转换为带有st_as_sf的点几何图形并绘制它,以显示它的外观。
  3. 最后,我们可以使用st_within检查每个点是否在nz边界内。 st_within返回每个点的点所在的多边形索引列表,因此我们可以使用lengths来获得我们想要的结果。这里0的任何内容都不在边界内,1的任何内容都在边界内。使用此新on_land属性进行绘图可显示离岸点已适当着色。
  4. library(tidyverse)
    library(sf)
    #> Linking to GEOS 3.6.1, GDAL 2.2.3, proj.4 4.9.3
    library(rnaturalearth)
    
    nz <- ne_countries(country = "New Zealand", returnclass = "sf", scale = "large") %>%
      st_cast("POLYGON") %>%
      mutate(area = st_area(geometry)) %>%
      top_n(3, area)
    #> Warning in st_cast.sf(., "POLYGON"): repeating attributes for all sub-
    #> geometries for which they may not be constant
    
    points <- tibble(
      x = runif(1000, st_bbox(nz)[1], st_bbox(nz)[3]),
      y = runif(1000, st_bbox(nz)[2], st_bbox(nz)[4])
    )
    points
    #> # A tibble: 1,000 x 2
    #>        x     y
    #>    <dbl> <dbl>
    #>  1  167. -44.5
    #>  2  175. -40.9
    #>  3  177. -43.8
    #>  4  167. -44.8
    #>  5  173. -39.3
    #>  6  173. -42.1
    #>  7  176. -41.9
    #>  8  171. -44.9
    #>  9  173. -41.2
    #> 10  174. -39.5
    #> # ... with 990 more rows
    points <- st_as_sf(points, coords = c("x", "y"), crs = 4326)
    plot(nz$geometry, col = "red")
    plot(points, pch = 19, cex = 1, add = TRUE)
    

    points <- points %>% mutate(on_land = lengths(st_within(points, nz)))
    #> although coordinates are longitude/latitude, st_within assumes that they are planar
    plot(nz$geometry, col = "red")
    plot(points, pch = 19, cex = 1, add = TRUE)
    

    reprex package(v0.2.0)创建于2018-05-02。

答案 1 :(得分:0)

您可以使用maps::map.where和(如果需要)自定义地图,只包含3个主要岛屿:

nz3 = map("nz",c("North","South","Stewart"), fill=TRUE, plot=FALSE)
points$onland = is.na(map.where(nz3, points$x, points$y))
plot(points, col = ifelse(points$onland, 1, 2), pch=19)