【发布时间】:2018-12-24 12:06:26
【问题描述】:
我有 3 亿个点想要与 6000 万个多边形相交。这两者的组合比我可以轻松放入机器内存的容量更大。我已经推出了一个解决方案,我将每个数据集加载到 PostGIS 中,对每个数据集执行空间索引,然后执行空间连接。
在 PostGIS 中看起来像:
SELECT pts.*, grid.gridID
into test_join
FROM pts, grid
WHERE ST_Contains( grid.geometry, pts.geometry);
pts(3 亿点)上的空间索引大约需要 90 分钟。然后上面的加入大约需要 190 分钟。
我以前从未使用R 处理过大于 RAM 的空间数据。
- 有没有办法使用
R中的sf包来处理这种规模的数据? - 存在哪些加快此操作的策略?
- 我应该考虑其他工具或方法吗?
我更喜欢使用开源工具(R、PostGIS、Python 等)。但我并不致力于任何特定的工具链。
其他数据 似乎我没有说明具体的解决方案造成了混乱。我最初没有提供任何语法或示例的原因是我不拘泥于特定平台。我对使用任何开源堆栈的想法持开放态度。正如标题所说,我在文中重申,这里的问题是规模,而不是解决一个琐碎示例的语法。
这是一个非常具体的解决方案,使用 R 中的 sf 包解决。下面的示例适用于 500 平方公里和 1000 个随机点的美国网格。我想将其扩展到 1 公里以下的网格和 300,000,000 个点。我根本不关心绘图,但我在下面绘制了一些东西仅用于说明。
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.1.3, PROJ 4.9.3
library(tidyverse)
library(spData)
#> To access larger datasets in this package, install the spDataLarge
#> package with: `install.packages('spDataLarge',
#> repos='https://nowosad.github.io/drat/', type='source'))`
# size of squares in projection units (in this case meters)
grid_size <- 500000
num_pts <- 1000 # number of points to join
data(us_states) # loads the us_states shape
all_states <-
us_states %>%
# st_sf() %>%
st_transform(102003) %>% # project to a meters based projection
st_combine %>% #flattens the shape file to one big outline (no states)
st_buffer(10000) # add a 10k buffer
#a nice outter buffer of the usa lower 48
ggplot() +
geom_sf(data = all_states)
## let's put a grid over the whole US
state_box <- st_bbox(all_states)
xrange <- state_box$xmax - state_box$xmin
yrange <- state_box$ymax - state_box$ymin
cell_dim <-
c(ceiling(xrange / grid_size),
ceiling(yrange / grid_size)) # dimension of polygons necessary
full_us_grid <-
st_make_grid(all_states, square = TRUE, n = cell_dim) %>%
st_intersection(all_states) %>% # only the inside part
st_sf() %>%
mutate(grid_id = 1:n())
ggplot() +
geom_sf(data = full_us_grid)
## now let's create some random points
random_pts <- data.frame(
point_id = 1:num_pts,
lat = runif(num_pts, 30, 50),
lon = runif(num_pts, -117, -78)
) %>%
# these are in degrees so need crs in same
st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
st_transform(102003) # transform into our metric crs
ggplot() +
geom_sf(data = full_us_grid) +
geom_sf(data = random_pts)
## here is the spatial join!!
joined_data <-
full_us_grid %>%
st_join(random_pts)
## this is the mapping from grid_id to point_id
joined_data %>%
st_set_geometry(NULL) %>%
na.omit() %>%
head
#> grid_id point_id
#> 7 7 26
#> 7.1 7 322
#> 7.2 7 516
#> 7.3 7 561
#> 7.4 7 641
#> 7.5 7 680
由reprex package (v0.2.1) 于 2018 年 12 月 24 日创建
【问题讨论】:
-
你能提供一些包含几个点和多边形的示例数据吗?