【问题标题】:How to Bound the Outer Area of Voronoi Polygons and Intersect with Map Data如何界定 ​​Voronoi 多边形的外部区域并与地图数据相交
【发布时间】:2016-07-13 07:41:40
【问题描述】:

背景

我正在尝试在美国地图上使用voronoi polygons 在以下data 上可视化kmeans 聚类过程的结果。

这是我目前一直在运行的代码:

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)

制作以下内容

问题

我希望能够绑定多边形的外部区域并将生成的区域与我的美国地图相交,以便多边形完全代表美国的陆地区域。我一直无法弄清楚如何做到这一点。非常感谢任何帮助。

【问题讨论】:

    标签: r ggplot2 cluster-analysis data-visualization voronoi


    【解决方案1】:

    我提出这个问题的最终目标是编写一个脚本,我可以在其中任意更改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 多边形与美国地图完美匹配,我从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)
    

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

    更新摘要

    重叠的voronoi 多边形仍然不是一个完美的拟合(我猜是由于太平洋西北部缺乏输入数据),尽管我认为这应该是一个简单的修复,我会尝试尽快更新。此外,如果我在函数开始时更改 kmeans centroids 的数量,然后重新运行所有多边形,那么多边形看起来一点也不好看,这不是我最初希望的。我会继续更新改进。

    【讨论】:

      猜你喜欢
      • 2017-07-07
      • 2015-10-20
      • 2014-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 2016-01-04
      • 1970-01-01
      相关资源
      最近更新 更多