Creating Voronoi Diagrams with ggplot

A Voronoi diagram (or tessellation) is neat way of visualizing spatial data. It essentially allows us to see the areas that are closest to a set of locations. For example, this map shows all of the Criagslist localities and the regions closest to each Craigslist locality. More formally, “A set of points (called seeds, sites, or generators) is specified beforehand and for each seed there will be a corresponding region consisting of all points closer to that seed than to any other.” (Wikipedia)

A handy library for plotting these in R is deldir. After installing that library (and ggplot2 if you don’t already have it), plotting a Voronoi diagram is simple.

#Let's generate some fake data
set.seed(105)
long<-rnorm(20,-98,15)
lat<-rnorm(20,39,10)
df <- data.frame(lat,long)

library(deldir)
library(ggplot2)

#This creates the voronoi line segments
voronoi <- deldir(df$long, df$lat)

#Now we can make a plot
ggplot(data=df, aes(x=long,y=lat)) +
  #Plot the voronoi lines
  geom_segment(
    aes(x = x1, y = y1, xend = x2, yend = y2),
    size = 2,
    data = voronoi$dirsgs,
    linetype = 1,
    color= "#FFB958") + 
  #Plot the points
  geom_point(
    fill=rgb(70,130,180,255,maxColorValue=255),
    pch=21,
    size = 4,
    color="#333333") +
  #(Optional) Specify a theme to use
  ltd_theme

You should end up with something like this:A sample Voronoi diagram plotAdditionally, if you would prefer the Delaunay triangulation (which connects all of the sites), you just need to change voronoi$dirsgs to voronoi$delsgs in the line segment part of the plot. Here’s what that should look like:A sample Delaunay triangulation plotI have not found a fully automated solution to combine these plots with a map. However, using the ggmap library can get you pretty close.

Tagged on: , , , , ,

7 thoughts on “Creating Voronoi Diagrams with ggplot

  1. PAC

    I think that in the first graph, you’ve plotted voronoi$dirsgs instead of voronoi$delsgs.

    Would you know how to create polygons instead of segments ?

  2. Pingback: Pasando el rato con las estaciones meteorológicas de Madrid. | Café con datos

  3. Al

    This example is really clear!
    But how to add ID labels
    to each blue “node”
    (ie: “A”, “B”, “C”…).

    With a label (ID)
    for each blue node ,
    this code would really be more useful
    in a real-world application…

    What would be the R code?

    Thanks!

      1. Ray Al

        Thank you, Phillip!
        Done.

        Reason for my question:
        Imagine you have 26 cell antennas,
        each labeled with a single, unique letter:
        A to Z.

        Ideally, at any time
        given your mobile location (latitude, longitude)
        you’d like to use the antenna closest to your location.
        Take a peek!
        your example code with deldir and ggplot2:

        #Let's generate some fake data
        set.seed(105)
        long<-rnorm(26,-98,15)
        lat<-rnorm(26,39,10)
        df <- data.frame(lat,long,name=c(LETTERS))
        library(deldir)
        library(ggplot2)
        #This creates the voronoi line segments
        voronoi <- deldir(df$long, df$lat)
        #Now we can make a plot
        ggplot(data=df, aes(x=long,y=lat)) +
           
        #Plot the voronoi lines
            geom_segment(
                aes(x = x1, y = y1, xend = x2, yend = y2),
                size = 1,
                data = voronoi$dirsgs,
                # or for Delaunay lines btw pts., use: data=voronoi$delsgs
                linetype = 1,
                color= "#FFB958") +
            geom_text(aes(label=df$name),hjust=-0.5, vjust=0) +
          
         #Plot the points
            geom_point(
                fill=rgb(70,130,180,255,maxColorValue=255),
                pch=21,
                size = 2,
                color="#333333")
        

        So, from this generated Voronoi diagram,
        you can visually "see" that a location:
        long= -110 and lat = 40
        places you in the region with the R antenna.
        That's the closest antenna to where you are now.

        But, the question is…
        without looking at this Voronoi diagram,
        how to input this (lat, long) location to deldir()
        to simply get the value:
        "R"
        as an output antenna result?
        (computationally, not visually…).

        Is there a deldir() option/parameter for this?

Leave a Reply

Your email address will not be published. Required fields are marked *