r - 如何界定 ​​Voronoi 多边形的外部区域并与 map 数据相交

标签 r ggplot2 cluster-analysis data-visualization voronoi

背景

我正在尝试可视化以下 datakmeans 聚类过程的结果。在美国 map 上使用 voronoi 多边形

这是我迄今为止运行的代码:

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)

生成以下内容

Voronoi Polygons on US Map

问题

我希望能够绑定(bind)多边形的外部区域并将结果区域与我的美国 map 相交,以便多边形完全代表美国陆地区域。但我还不知道如何做到这一点。非常感谢任何帮助。

最佳答案

我提出这个问题的最终目标是编写一个脚本,在其中我可以任意更改 kmeans 簇的数量,并使用覆盖我的 voronoi 多边形快速可视化结果所需区域。

我还没有完全完成这一点,但我已经取得了足够的进展,我认为发布我所拥有的内容可能会带来更快的解决方案。

# 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"))

我还发现了以下内容。 function在网上寻找解决方案时。

# 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)
}

通过上述函数定义的多边形可以相应地提取

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

为了让 voronoi 多边形与我下载的美国 map 完美契合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)

从这里我可以像以前一样使用 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)

enter image description here

更新摘要

重叠的 voronoi 多边形仍然不是完美的配合(我猜测是由于太平洋西北地区缺乏输入数据),尽管我认为这应该是一个简单的修复,并且我会尽力尽快更新。另外,如果我在函数开头更改 kmeans centroids 的数量,然后重新运行所有内容,则多边形看起来一点也不好看,这不是我最初希望的。我将继续更新并改进。

关于r - 如何界定 ​​Voronoi 多边形的外部区域并与 map 数据相交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36221822/

相关文章:

正则表达式提取不包含在双引号中的字符串

r - 子集的编程安全版本 - 在从另一个函数调用时评估其条件

r - 如何用R中的NA输出替换函数错误?

r - ggplotly 错误顺序为 : argument 1 is not a vector

r - 饼图将其文本置于彼此之上

python - 对于DBSCAN python,是否必须同时进行标准化和规范化?

machine-learning - 聚类实现异构组

regex - 在R中的其他两个字符串之间提取一个字符串

r - 使用 ggplotly(ggplot2 with plotly)时,你能去掉注释中的跟踪标签吗?

python - scipy 中的层次聚类 - 内存错误