简体   繁体   English

如何绑定Voronoi多边形的外部区域并与地图数据相交

[英]How to Bound the Outer Area of Voronoi Polygons and Intersect with Map Data

Background 背景

I'm trying to visualize the results of a kmeans clustering procedure on the following data using voronoi polygons on a US map. 我正在尝试在美国地图上使用voronoi polygons对以下数据进行kmeans聚类过程的结果可视化。

Here is the code I've been running so far: 这是到目前为止我一直在运行的代码:

input <- read.csv("LatLong.csv", header = T, sep = ",")

# K Means Clustering

set.seed(123)
km <- kmeans(input, 17)
cent <- data.frame(km$centers)


# Visualization
states <- map_data("state")
StateMap <- ggplot() + geom_polygon(data = states, aes(x = long, y = lat, group = group), col = "white")

# Voronoi
V <- deldir(cent$long, cent$lat)

ll <-apply(V$dirsgs, 1, FUN = function(x){
  readWKT(sprintf("LINESTRING(%s %s, %s %s)", x[1], x[2], x[3], x[4]))
})

pp <- gPolygonize(ll)=
v_df <- fortify(pp)


# Plot
StateMap +
  geom_point(data = input, aes(x = long, y = lat), col = factor(km$cluster)) +
  geom_polygon(data = v_df, aes(x = long, y = lat, group = group, fill = id), alpha = .3) +
  geom_label(data = cent, aes(x = long, y = lat, label = row.names(cent)), alpha = .3)

Producing the Following 产生以下

美国地图上的Voronoi多边形

Question

I'd like to be able to bind the outer area of the polygons and intersect the resulting area with my map of the United States so that the polygons entirely represent US land area. 我希望能够绑定多边形的外部区域并将其与我的美国地图相交,以便多边形完全代表美国的陆地区域。 I haven't been able to figure out how to do this though. 我还没办法弄清楚该怎么做。 Any help is greatly appreciated. 任何帮助是极大的赞赏。

My end goal in asking this question was to write a script where I can arbitrarily change the number of kmeans clusters and quickly visualize the results with voronoi polygons that cover my desired area region. 我提出这个问题的最终目的是编写一个脚本,在其中我可以任意更改kmeans簇的数量,并使用覆盖我想要的区域的voronoi多边形快速可视化结果。

I haven't quite accomplished this yet, but I have made enough progress that I figured posting what I have may lead to a quicker solution. 我还没有完全做到这一点,但是我已经取得了足够的进步,以至于我发现发布的内容可能会导致更快的解决方案。

# Create Input Data.Frame
input <- as.data.frame(cbind(x$long, x$lat))
colnames(input) <- c("long", "lat")

# Set Seed and Run Clustering Procedure
set.seed(123)
km <- kmeans(input, 35)

# Format Output for Plotting
centers <- as.data.frame(cbind(km$centers[,1], km$centers[,2]))
colnames(centers) <- c("long", "lat")
cent.id <- cbind(ID = 1:dim(centers)[1], centers)

# Create Spatial Points Data Frame for Calculating Voronoi Polygons
coords  <- centers[,1:2]
vor_pts <- SpatialPointsDataFrame(coords, centers, proj4string = CRS("+proj=longlat +datum=WGS84"))

I also found the below. 我还发现了以下内容。 function while searching for a solution online. 功能 ,同时寻找解决的办法上网。

# Function to Extract Voronoi Polygons 

SPdf_to_vpoly <- function(sp) {

  # tile.list extracts the polygon data from the deldir computation
  vor_desc <- tile.list(deldir(sp@coords[,1], sp@coords[,2]))

  lapply(1:length(vor_desc), function(i) {

    # tile.list gets us the points for the polygons but we 
    # still have to close them, hence the need for the rbind

    tmp <- cbind(vor_desc[[i]]$x, vor_desc[[i]]$y)
    tmp <- rbind(tmp, tmp[1,])

    # Now we can make the polygons
    Polygons(list(Polygon(tmp)), ID = i)
  }) -> vor_polygons
  # Hopefully the caller passed in good metadata
  sp_dat <- sp@data

  # This way the IDs should match up with the data & voronoi polys
  rownames(sp_dat) <- sapply(slot(SpatialPolygons(vor_polygons), 'polygons'), slot, 'ID')

  SpatialPolygonsDataFrame(SpatialPolygons(vor_polygons), data = sp_dat)
}

With the above function defined polygons can be extracted accordingly 通过上述功能,可以相应地提取多边形

vor     <- SPdf_to_vpoly(vor_pts)
vor_df  <- fortify(vor)

In order to get the voronoi polygons to fit nicely with a US map I downloaded cb_2014_us_state_20m from the Census website and ran the following: 为了使voronoi多边形与美国地图很好地匹配,我从Census网站下载了cb_2014_us_state_20m并运行了以下命令:

# US Map Plot to Intersect with Voronoi Polygons - download from census link and place in working directory
us.shp <- readOGR(dsn = ".", layer = "cb_2014_us_state_20m")
state.abb <- state.abb[!state.abb %in% c("HI", "AK")]

Low48 <- us.shp[us.shp@data$STUSPS %in% state.abb,]

# Define Area Polygons and Projections and Calculate Intersection
Low48.poly <- as(Low48, "SpatialPolygons")
vor.poly   <- as(vor, "SpatialPolygons")

proj4string(vor.poly) <- proj4string(Low48.poly)
intersect  <- gIntersection(vor.poly, Low48.poly, byid = T)


# Convert to Data Frames to Plot with ggplot
Low48_df <- fortify(Low48.poly)
int_df   <- fortify(intersect)

From here I could visualize my results using ggplot like before: 从这里,我可以像以前一样使用ggplot可视化我的结果:

# Plot Results
StateMap <- ggplot() + geom_polygon(data = Low48_df, aes(x = long, y = lat, group = group), col = "white")

StateMap +
  geom_polygon(data = int_df, aes(x = long, y = lat, group = group, fill = id), alpha = .4) +
  geom_point(data = input, aes(x = long, y = lat), col = factor(km$cluster)) +
  geom_label(data = centers, aes(x = long, y = lat, label = row.names(centers)), alpha =.2) +
  scale_fill_hue(guide = 'none') +
  coord_map("albers", lat0 = 30, lat1 = 40)

在此处输入图片说明

Summary of Updates 更新摘要

The overlapping voronoi polygons still aren't a perfect fit (I'm guessing due to a lack of input data in the pacific northwest) although I'd imagine that should be a simple fix and I'll try to update that as soon as possible. 重叠的voronoi多边形仍然不是一个完美的拟合(我想是由于西北太平洋地区缺乏输入数据),尽管我认为这应该是一个简单的解决方法,我会尽快对其进行更新。可能。 Also if I alter the number of kmeans centroids in the beginning of my function and then re-run everything the polygons don't look very nice at all which is not what I was originally hoping for. 另外,如果我在函数开始时更改了kmeans centroids的数量,然后重新运行所有多边形,这些多边形看起来根本不是很好,这并不是我最初希望的。 I'll continue to update with improvements. 我将继续改进。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM