英文:
Connect multiple polygons from the same shapefile
问题
I want to connect ALL the states drew from a sample of states of USA with a thin line exactly how it is done in this post.
我想要连接从美国各州的样本中绘制出的所有州,以确切地如此帖子中所做的那样,使用细线连接。
I did manage to draw some lines between some polygons but I did not manage to draw lines so all polygons are connected at the end. How can I force a polygon already connected to look for making a connexion with a polygon that is not already linked with itself?
我成功地在一些多边形之间绘制了一些线,但我没有成功地绘制线,以使所有多边形在最后都连接起来。我该如何强制已经连接的多边形寻找与尚未与其自身连接的多边形建立连接的方法?
Here is my code:
这是我的代码:
library(dplyr)
library(sf)
library(ggplot2)
library(nngeo)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
set.seed(2806)
nc_sample <- dplyr::sample_n(nc, 10)
ggplot() + geom_sf(data = nc_sample)
co <- st_connect(nc_sample[1,], nc_sample %>% slice(st_distance(nc_sample[1,],nc_sample) %>%
units::drop_units() %>%
as.data.frame() %>%
mutate_if(is.numeric, ~na_if(., 0)) %>%
rowwise() %>%
which.min()))
all_connexion <- st_sf(co)
for(i in 2:length(nc_sample$AREA)){
co <- st_connect(nc_sample[i,], nc_sample %>% slice(st_distance(nc_sample[i,],nc_sample) %>%
units::drop_units() %>%
as.data.frame() %>%
mutate_if(is.numeric, ~na_if(., 0)) %>%
rowwise() %>%
which.min()))
all_connexion <- rbind(all_connexion, co)
}
ggplot() +
geom_sf(data = all_connexion) +
geom_sf(data = nc_sample)
and the connexion I get:
我获得的连接如下:
<details>
<summary>英文:</summary>
I want to connect **ALL** the states drew from a *sample of states of USA* with a thin line exactly how it is done in this [post][1].
I did manage to draw some lines between some polygons but I did not manage to draw lines so all polygons are connected at the end. How can I force a polygon already connected to look for making a connexion with a polygon that is not already linked with itself?
Here is my code :
library(dplyr)
library(sf)
library(ggplot2)
library(nngeo)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
set.seed(2806)
nc_sample=dplyr::sample_n(nc,10)
ggplot() + geom_sf(data = nc_sample)
co=st_connect(nc_sample[1,], nc_sample %>% slice(st_distance(nc_sample[1,],nc_sample) %>%
units::drop_units() %>%
as.data.frame() %>%
mutate_if(is.numeric, ~na_if(., 0)) %>%
rowwise() %>% which.min()))
all_connexion=st_sf(co)
for(i in 2:length(nc_sample$AREA)){
co=st_connect(nc_sample[i,], nc_sample %>% slice(st_distance(nc_sample[i,],nc_sample) %>%
units::drop_units() %>%
as.data.frame() %>%
mutate_if(is.numeric, ~na_if(., 0)) %>%
rowwise() %>% which.min()))
all_connexion = rbind(all_connexion,co)
}
ggplot() +
geom_sf(data = all_connexion) +
geom_sf(data = nc_sample)
and the connexion I get :
[![enter image description here][2]][2]
[1]: https://stackoverflow.com/questions/66936153/daisychain-connect-multiple-polygons-by-single-nearest-points
[2]: https://i.stack.imgur.com/qVREn.png
</details>
# 答案1
**得分**: 4
要使用 `nngeo`,您可以迭代多边形,每次找到尚未连接的集合中最近的邻居。基本上是旅行推销员问题的最近邻算法。还请注意 `nc` 数据集包含多边形,要连接每个单独的多边形,您需要类似 `st_cast(nc_sample, "POLYGON")` 这样的东西首先。
``` r
库(dplyr)
库(sf)
库(ggplot2)
库(nngeo)
nc <- 读取(st_read(system.file("shape/nc.shp", package="sf")))
设置种子(2806)
nc_sample=dplyr::sample_n(nc,10) %>%
# 添加索引和next_hop列
变异(id = 行编号(),
next_hop = NA_integer_)
# 迭代多边形列表,
# 找到未连接多边形集合中最近的邻居
# 起始多边形索引:
idx <- 1
# 未连接多边形的掩码:
nn_mask <- rep_len(TRUE, nrow(nc_sample))
nn_mask[idx] <- FALSE
while (any(nn_mask)) {
# 掩码数据集中最近邻居的索引
masked_idx <- st_nn(nc_sample[idx,],
nc_sample[nn_mask,],
k = 1,
progress = FALSE)[[1]]
# 获取/存储匹配的id值
idx <- nc_sample$next_hop[idx] <- nc_sample[nn_mask,]$id[masked_idx]
# 从可用多边形集中排除最新匹配
nn_mask[idx] <- FALSE
}
# 结果连接:
st_drop_geometry(nc_sample)[,c("id", "next_hop")]
#> id next_hop
#> 1 1 6
#> 2 2 5
#> 3 3 NA
#> 4 4 2
#> 5 5 3
#> 6 6 10
#> 7 7 9
#> 8 8 7
#> 9 9 4
#> 10 10 8
connections <- st_connect(nc_sample, nc_sample, ids = nc_sample$next_hop)
ggplot(nc_sample) +
geom_sf() +
geom_sf_label(aes(label = id)) +
geom_sf(data = connections)
<!-- -->
<sup>创建于2023-06-29,使用reprex v2.0.2</sup>
在大多数情况下,您可能希望通过图形和更高级的TSP方法来解决这个问题,所以也许要检查igraph
和TSP
包。
英文:
To use nngeo
, you could iterate through polygons, each time finding the closest neighbour from the set that has not been linked yet. It's basically the nearest neighbour algorithm for the travelling salesman problem. Also note that nc
dataset contains multipolygons, to connect each individual polygon, you would need something like st_cast(nc_sample, "POLYGON")
first.
library(dplyr)
library(sf)
library(ggplot2)
library(nngeo)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
set.seed(2806)
nc_sample=dplyr::sample_n(nc,10) %>%
# add index and next_hop columns
mutate(id = row_number(),
next_hop = NA_integer_)
# iterate though list of ploygons,
# find the closest neighbour from set of polygons
# that are not yet linked
# starting polygon index:
idx <- 1
# mask for unlinked polygons:
nn_mask <- rep_len(TRUE, nrow(nc_sample))
nn_mask[idx] <- FALSE
while (any(nn_mask)) {
# index of the nearest neighbour in masked dataset
masked_idx <- st_nn(nc_sample[idx,],
nc_sample[nn_mask,],
k = 1,
progress = FALSE)[[1]]
# get / store matching id value
idx <- nc_sample$next_hop[idx] <- nc_sample[nn_mask,]$id[masked_idx]
# exclude latest match from the set of available polygons
nn_mask[idx] <- FALSE
}
# resulting connections:
st_drop_geometry(nc_sample)[,c("id", "next_hop")]
#> id next_hop
#> 1 1 6
#> 2 2 5
#> 3 3 NA
#> 4 4 2
#> 5 5 3
#> 6 6 10
#> 7 7 9
#> 8 8 7
#> 9 9 4
#> 10 10 8
connections <- st_connect(nc_sample, nc_sample, ids = nc_sample$next_hop)
ggplot(nc_sample) +
geom_sf() +
geom_sf_label(aes(label = id)) +
geom_sf(data = connections)
<!-- -->
<sup>Created on 2023-06-29 with reprex v2.0.2</sup>
In most cases you'd probably want solve this through graphs and more advanced TSP methods, so perhaps check igraph
and TSP
packages.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论