Fill voronoi polygons with ggplot - r

i want to fill voronoi polygons with colours based on a variable (z in my case). Here's the code:
library(rgdal)
library(deldir)
library(dplyr)
library(ggplot2)
library(UScensus2010)
x<-c(0,55,105,165,270,65,130,155,155,225,250,295,
30,100,110,135,160,190,230,300,30,70,105,170,
210,245,300,0,85,175,300,15,60,90,90,140,210,
260,270,295,5,55,55,90,100,140,190,255,285,270)
y<-c(305,310,305,310,310,260,255,265,285,280,250,
260,210,240,225,225,225,230,210,215,160,190,
190,175,160,160,170,120,135,115,110,85,90,90,
55,55,90,85,50,50,25,30,5,35,15,0,40,20,5,150)
z<-c(870,793,755,690,800,800,730,728,710,780,804,
855,813,762,765,740,765,760,790,820,855,812,
773,812,827,805,840,890,820,873,875,873,865,
841,862,908,855,850,882,910,940,915,890,880,
870,880,960,890,860,830)
dati<-data.frame(x,y,z)
vor_pts <- SpatialPointsDataFrame(cbind(dati$x,dati$y),dati, match.ID=TRUE)
SPointsDF_to_voronoi_SPolysDF <- 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 Polygon(s)
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 w/the data & voronoi polys
rownames(sp_dat) <- sapply(slot(SpatialPolygons(vor_polygons),
'polygons'),
slot, 'ID')
SpatialPolygonsDataFrame(SpatialPolygons(vor_polygons),
data=sp_dat)
}
vor <- SPointsDF_to_voronoi_SPolysDF(vor_pts)
vor_df <- fortify(vor)
ggplot() +
geom_point(data = dati, aes(x, y), shape=21,
color = "white", fill = "steel blue") +
geom_map(data = vor_df, map = vor_df, aes(x = long, y = lat, map_id = id),
color = "#a5a5a5", fill = "#FFFFFF00", size = 0.25)
Now I have this image:
I want that each polygon should be mapped to a color scale based on the value of variable z... how can i do that?? Thanks!!!

As far as I know, you can't use a vector that isn't the same length as the data problem itself (in this case the number of rows in vor_df) to specify fill colors. However, if I make the assumption that each of the elements from z is to be applied to the id of a shape from vor_df, you could do this;
ggplot() +
geom_map(data=vor_df, map=vor_df,aes(x=long, y=lat, map_id=id, fill = id), size=0.25) +
geom_path(data=vor_df,aes(x=long, y=lat, map=id)) +
geom_point(data = dati, aes(x, y),shape=21, color="white", fill="steelblue")
This maps the id column to each polygon as a color. It should be easy enough to add a seperate column to add a value to each id based on vector z if you need it in the legend or any number of other things.
Though, this is all on the assumption that each id directly correlates to a number from vector z.

Simply use tileplot in latticeExtra package:
library(deldir)
library(latticeExtra)
tileplot(z~x*y, dati)
here is the output

Related

Using geom_text() to display text in geom_polygon() [duplicate]

I am trying to label my polygons by using ggplot in R. I found a topic here on stackoverflow that I think is very close to what I want except with points.
Label points in geom_point
I found some methods online. Now I first need to find the central location of each shape and then I have to put these locations together with the name together. Then link this to the labeling function in geom_text()
ggplot centered names on a map
Since I have been trying for a long time now I decided to ask the question and hope that someone here can give me the final push to what I want. My plotting function:
region_of_interest.fort <- fortify(region_of_interest, region = "score")
region_of_interest.fort$id <- as.numeric(region_of_interest.fort$id)
region_of_interest.fort$id <- region_of_interest.fort$id
region_of_interest.fort1 <- fortify(region_of_interest, region = "GM_NAAM")
region_of_interest.fort1$id <- as.character(region_of_interest.fort1$id)
region_of_interest.fort1$id <- region_of_interest.fort1$id
idList <- unique(region_of_interest.fort1$id)
centroids.df <- as.data.frame(coordinates(region_of_interest))
names(centroids.df) <- c("Longitude", "Latitude")
randomMap.df <- data.frame(id = idList, shading = runif(length(idList)), centroids.df)
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
It gives me the error: ggplot2 doesn't know how to deal with data of class uneval
My data
region_of_interest$GM_NAAM
[1] Groningen Haren Ooststellingwerf Assen Aa en Hunze Borger- Odoorn
[7] Noordenveld Westerveld Tynaarlo Midden-Drenthe
415 Levels: 's-Gravenhage 's-Hertogenbosch Aa en Hunze Aalburg Aalsmeer Aalten ... Zwolle
region_of_interest$score
[1] 10 -2 -1 2 -1 -4 -4 -5 0 0
Try something like this?
Get a data frame of the centroids of your polygons from the
original map object.
In the data frame you are plotting, ensure there are columns for
the ID you want to label, and the longitude and latitude of those
centroids.
Use geom_text in ggplot to add the labels.
Based on this example I read a world map, extracting the ISO3 IDs to use as my polygon labels, and make a data frame of countries' ID, population, and longitude and latitude of centroids. I then plot the population data on a world map and add labels at the centroids.
library(rgdal) # used to read world map data
library(rgeos) # to fortify without needing gpclib
library(maptools)
library(ggplot2)
library(scales) # for formatting ggplot scales with commas
# Data from http://thematicmapping.org/downloads/world_borders.php.
# Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
# Unpack and put the files in a dir 'data'
worldMap <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Change "data" to your path in the above!
worldMap.fort <- fortify(world.map, region = "ISO3")
# Fortifying a map makes the data frame ggplot uses to draw the map outlines.
# "region" or "id" identifies those polygons, and links them to your data.
# Look at head(worldMap#data) to see other choices for id.
# Your data frame needs a column with matching ids to set as the map_id aesthetic in ggplot.
idList <- worldMap#data$ISO3
# "coordinates" extracts centroids of the polygons, in the order listed at worldMap#data
centroids.df <- as.data.frame(coordinates(worldMap))
names(centroids.df) <- c("Longitude", "Latitude") #more sensible column names
# This shapefile contained population data, let's plot it.
popList <- worldMap#data$POP2005
pop.df <- data.frame(id = idList, population = popList, centroids.df)
ggplot(pop.df, aes(map_id = id)) + #"id" is col in your df, not in the map object
geom_map(aes(fill = population), colour= "grey", map = worldMap.fort) +
expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) +
scale_fill_gradient(high = "red", low = "white", guide = "colorbar", labels = comma) +
geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
labs(x = "Longitude", y = "Latitude", title = "World Population") +
theme_bw()
Minor technical note: actually coordinates in the sp package doesn't quite find the centroid, but it should usually give a sensible location for a label. Use gCentroid in the rgeos package if you want to label at the true centroid in more complex situations like non-contiguous shapes.
The accepted answer here may work, but the actual question asked specifically notes that there is an error "ggplot2 doesn't know how to deal with data of class uneval."
The reason that it is giving you the error is because the inclusion of centroids.df needs to be a named variable (e.g. accompanied by "data=")
Currently:
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
Should be (note: "data=centroids.df"):
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(data=centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
This issue was addressed here: How to deal with "data of class uneval" error from ggplot2?

create a map with the adapted size of states

Hi visualization lovers,
I am trying to create a color map plot,like this one:
(source: https://github.com/hrbrmstr/albersusa)
BUT i want this maps to be biased so that the areas of the states to be proportional to the value I provide (in particular,I use GPD value).
What i mean is that I want some states to look bigger, some smaller that they are in reality but reminding the real USA map as much as possible.
No problems with the states moving or shape destroying.
Any ideas? Any ready solutions?
Currently I use R and albersusa package because it is something I am familiar with. Open to change!
My current code for the plot is:
gmap<-
ggplot() +
geom_map(data = counties#data, map = cmap,
aes(fill =atan(y/x),alpha=x+y, map_id = name),
color = "gray50") +
geom_map(data = smap, map = smap,
aes(x = long, y = lat, map_id = id),
color = "black", size = .5, fill = NA) +
theme_map(base_size = 12) +
theme(plot.title=element_text(size = 16, face="bold",margin=margin(b=10))) +
theme(plot.subtitle=element_text(size = 14, margin=margin(b=-20))) +
theme(plot.caption=element_text(size = 9, margin=margin(t=-15),hjust=0)) +
scale_fill_viridis()+guides(alpha=F,fill=F)
Here's a very ugly first try to get you started, using the outlines from the maps package and some data manipulation from dplyr.
library(maps)
library(dplyr)
library(ggplot2)
# Generate the base outlines
mapbase <- map_data("state.vbm")
# Load the centroids
data(state.vbm.center)
# Coerce the list to a dataframe, then add in state names
# Then generate some random value (or your variable of interest, like population)
# Then rescale that value to the range 0.25 to 0.95
df <- state.vbm.center %>% as.data.frame() %>%
mutate(region = unique(mapbase$region),
somevalue = rnorm(50),
scaling = scales::rescale(somevalue, to = c(0.25, 0.95)))
df
# Join your centers and data to the full state outlines
df2 <- df %>%
full_join(mapbase)
df2
# Within each state, scale the long and lat points to be closer
# to the centroid by the scaling factor
df3 <- df2 %>%
group_by(region) %>%
mutate(longscale = scaling*(long - x) + x,
latscale = scaling*(lat - y) + y)
df3
# Plot both the outlines for reference and the rescaled polygons
ggplot(df3, aes(long, lat, group = region, fill = somevalue)) +
geom_path() +
geom_polygon(aes(longscale, latscale)) +
coord_fixed() +
theme_void() +
scale_fill_viridis()
These outlines aren't the best, and the centroid positions they shrink toward cause the polygons to sometimes overlap the original state outline. But it's a start; you can find better shapes for US states and various centroid algorithms.

Using ggplot to plot a map from a matrix

I wanted to create some maps by using ggplot2, but I am struggling to find the best way. Since I have a list ("models") with matrix, I wanted to use ggplot because then, it should be easier to create a multiplot (with facet_wrap..but just a thought).
I will create an reproducible example for doing this:
#European corrdinates
lon <- rep(loni,38) #longitude values -13W-34E
lat <- rep(lati, each = 48) #latitude values 34N-70N
#Matrix of values
mod <- matrix( rnorm(48*38,mean=0,sd=1), 48, 38)
#Create a list of matrix (as my real data)
dat.mod <- rep(list(mod), 4)
names(dat.mod) <- c("DJF","MAM","JJA","SON")
#Order data
md <- melt(dat.mod)
md$lon <- lon
md$lat <- lat
md$group <- "Model1"
names(md) <- c("X1","X2","SI","Season","lon","lat","model")
#
#First try:
#Problem here: I don't know how to add the map
brks <- seq(0, 2.2, by=0.2)
cols <- colorRampPalette(c("skyblue1", "lightcyan2", "lightyellow", "yellow", "orange", "red3"))(length(brks)-1)
m <- ggplot(data = md, aes(x = lon, y = lat, fill = SI)) +
geom_raster() +
scale_fill_gradientn(colours = cols, na.value = NA)+
facet_wrap(~ model~ Season, nrow =11,ncol=4)+
theme(strip.background = element_blank(),
strip.text.x = element_blank())
#I would get this image:
#Now, as a second try to add a map of Europe, I used:
map <- ggplot()
map <- map + coord_fixed()
map <- map + geom_polygon(data=map_data(map="world"), aes(x=long, y=lat, group=group), fill=NA, color="black", size=0.01)
map <- map + coord_cartesian(xlim=range(md$lon), ylim=range(md$lat))
map <- map + geom_tile(data=md, aes(x=lon, y=lat, fill=SI), alpha=I(0.7))
map <- map + scale_fill_gradientn(colours=cols)
map <- map + facet_grid(model~Season)
map <- map + theme(legend.position="none")
Now, I would have:
The problem with the second one is that I don't know how to change to background with white, and make the map more visible..is that possible?? The thing is, I wanted to plot 11 rows by 4 col. so when plotting all together it doesn't look very well...any suggestion?
Really appreciate any help.
Many thanks

world map - map halves of countries to different colors using ggplot2

I'm looking for a ggplot2 solution for this question:
world map - map halves of countries to different colors
I reproduce the example from that question below, which is based on the question here (ggplot map with l).
library(rgdal)
library(ggplot2)
library(maptools)
# Data from http://thematicmapping.org/downloads/world_borders.php.
# Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
# Unpack and put the files in a dir 'data'
gpclibPermit()
world.map <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
world.ggmap <- fortify(world.map, region = "NAME")
n <- length(unique(world.ggmap$id))
df <- data.frame(id = unique(world.ggmap$id),
growth = 4*runif(n),
category = factor(sample(1:5, n, replace=T)))
## noise
df[c(sample(1:100,40)),c("growth", "category")] <- NA
ggplot(df, aes(map_id = id)) +
geom_map(aes(fill = growth, color = category), map =world.ggmap) +
expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
scale_fill_gradient(low = "red", high = "blue", guide = "colorbar")
You've got a couple options. It's pretty straightforward to get the polygons plotted, but you can't have two different fill scales. This solution uses point-shape annotations, but can be changed to scale the geom_point by color (or both color and shape). I think that's the best you're going to be able to do save overlaying two maps by hand in a separate program.
You'll also (probably) want to tweak the U.S. bounding box since the center is a bit off (a few of them are, actually, but that one is really obvious).
I also removed Antarctica. You can add that back in if you want, but it's wasted plot real estate IMO.
library(rgdal)
library(ggplot2)
library(maptools)
library(rgeos)
library(RColorBrewer)
world.map <- readOGR(dsn="/Users/bob/Desktop/TM_WORLD_BORDERS_SIMPL-0.3/", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Get centroids of countries
theCents <- coordinates(world.map)
# extract the polygons objects
pl <- slot(world.map, "polygons")
# Create square polygons that cover the east (left) half of each country's bbox
lpolys <- lapply(seq_along(pl), function(x) {
lbox <- bbox(pl[[x]])
lbox[1, 2] <- theCents[x, 1]
Polygon(expand.grid(lbox[1,], lbox[2,])[c(1,3,4,2,1),])
})
# Slightly different data handling
wmRN <- row.names(world.map)
n <- nrow(world.map#data)
world.map#data[, c("growth", "category")] <- list(growth = 4*runif(n),
category = factor(sample(1:5, n, replace=TRUE)))
# Determine the intersection of each country with the respective "left polygon"
lPolys <- lapply(seq_along(lpolys), function(x) {
curLPol <- SpatialPolygons(list(Polygons(lpolys[x], wmRN[x])),
proj4string=CRS(proj4string(world.map)))
curPl <- SpatialPolygons(pl[x], proj4string=CRS(proj4string(world.map)))
theInt <- gIntersection(curLPol, curPl, id = wmRN[x])
theInt
})
# Create a SpatialPolygonDataFrame of the intersections
lSPDF <- SpatialPolygonsDataFrame(SpatialPolygons(unlist(lapply(lPolys,
slot, "polygons")), proj4string = CRS(proj4string(world.map))),
world.map#data)
whole <- world.map[grep("Antarctica", world.map$NAME, invert=TRUE),]
half <- lSPDF[grep("Antarctica", lSPDF$NAME, invert=TRUE),]
whole <- fortify(whole, region="ISO3")
half <- fortify(half, region="ISO3")
world.map$scaled_growth <- as.numeric(scale(world.map#data$growth,
center = min(world.map#data$growth),
scale = max(world.map#data$growth)))
growth <- world.map#data[,c("ISO3", "scaled_growth")]
colnames(growth) <- c("id", "scaled_growth")
growth$scaled_growth <- factor(as.numeric(cut(growth$scaled_growth, 8))) # make it discrete
half_centers <- data.frame(cbind(coordinates(gCentroid(lSPDF, byid = TRUE)),
id=world.map#data$ISO3, category=world.map#data$category))
half_centers$category <- factor(half_centers$category)
gg <- ggplot()
gg <- gg + geom_map(data=whole, map=whole, aes(x=long, y=lat, map_id=id), alpha=0, color="black", size=0.15)
gg <- gg + geom_map(data=growth, map=whole, aes(fill=scaled_growth, map_id=id))
gg <- gg + geom_map(data=half, map=half, aes(x=long, y=lat, map_id=id), fill="white")
gg <- gg + geom_point(data=half_centers, aes(x=x, y=y, shape=category), size=2)
gg <- gg + scale_fill_brewer(palette="Pastel2")
gg <- gg + scale_shape_discrete()
gg <- gg + coord_equal()
gg
I think you can get (effectively) two different fill scales, with a little hack of scale_fill_brewer and scale_fill_manual.
Here's my output:
I use the first bit of code from the other thread you posted in the question:
library(rgdal)
library(ggplot2)
library(maptools)
world.map <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Get centroids of countries
theCents <- coordinates(world.map)
# extract the polygons objects
pl <- slot(world.map, "polygons")
# Create square polygons that cover the east (left) half of each country's bbox
lpolys <- lapply(seq_along(pl), function(x) {
lbox <- bbox(pl[[x]])
lbox[1, 2] <- theCents[x, 1]
Polygon(expand.grid(lbox[1,], lbox[2,])[c(1,3,4,2,1),])
})
# Slightly different data handling
wmRN <- row.names(world.map)
n <- nrow(world.map#data)
world.map#data[, c("growth", "category")] <- list(growth = 4*runif(n),
category = factor(sample(1:5, n, replace=TRUE)))
# Determine the intersection of each country with the respective "left polygon"
lPolys <- lapply(seq_along(lpolys), function(x) {
curLPol <- SpatialPolygons(list(Polygons(lpolys[x], wmRN[x])),
proj4string=CRS(proj4string(world.map)))
curPl <- SpatialPolygons(pl[x], proj4string=CRS(proj4string(world.map)))
theInt <- gIntersection(curLPol, curPl, id = wmRN[x])
theInt
})
# Create a SpatialPolygonDataFrame of the intersections
lSPDF <- SpatialPolygonsDataFrame(SpatialPolygons(
unlist(lapply(lPolys,slot, "polygons")),
proj4string = CRS(proj4string(world.map))),
world.map#data)
Now my contribution (borrowing the names whole/half from user hrbrmstr!)
# get two data.frames, one with whole countries and the other with the left half
# this relies on code from SO user BenBarnes
whole <- fortify(world.map, region="ISO3")
half <- fortify(lSPDF, region="ISO3")
# random growth / category data, similar to the random data originally
# suggested by Xu Wang
set.seed(123)
df <- data.frame(id = unique(world.map#data$ISO3),
growth = 4*runif(n),
category = factor(sample(letters[1:5], n, replace=T)))
# make growth a factor; 5 levels for convenience
df$growth_fac <- cut(df$growth, 5)
# append growth and category factor levels together
growth_cat_levels <- c(levels(df$category), levels(df$growth_fac))
# adjust factors with new joint levels
df$growth_fac <-
factor(df$growth_fac, levels=growth_cat_levels)
df$category <-
factor(df$category, levels=growth_cat_levels)
# create a palette with some sequential colors and some qualitative colors
pal <- c(scale_fill_brewer(type='seq', palette=6)$palette(5),
scale_fill_brewer(type='qual', palette='Pastel2')$palette(5))
# merge data
whole <- data.frame(merge(whole, df, by='id'))
half <- data.frame(merge(half, df, by='id'))
# plot
ggplot() +
geom_polygon(data=whole,
aes(x=long, y=lat, group=group, fill=growth_fac),
color='black', size=0.15) +
geom_polygon(data=half,
aes(x=long, y=lat, group=group, fill=category),
color=NA) +
scale_shape_discrete() +
coord_equal() +
scale_fill_manual('Category, Growth',
values=pal, breaks=growth_cat_levels) +
guides(fill=guide_legend(ncol=2))
Some notes:
I still think this is a hard-to-read map, but a fun challenge
I changed the 'category' names from numeric to alpha, to help avoid confusion with the 'growth' data.
I also kept the 'growth' data labels as generated by cut, to help make it clear that this is binned continuous data.
At first, I had the Growth colors on the left hand side of the legend, but I swapped it around; since Category determines the fill color of the left side country polygons, I thought Category should appear on the left in the legend
I experimented with a couple different palette options. One danger is that the qualitative scale will have a color too similar to the range of the sequential scale (as was the case with my post prior to this edit). Having one side greyscale and one side with colors helps avoid this

Labeling center of map polygons in R ggplot

I am trying to label my polygons by using ggplot in R. I found a topic here on stackoverflow that I think is very close to what I want except with points.
Label points in geom_point
I found some methods online. Now I first need to find the central location of each shape and then I have to put these locations together with the name together. Then link this to the labeling function in geom_text()
ggplot centered names on a map
Since I have been trying for a long time now I decided to ask the question and hope that someone here can give me the final push to what I want. My plotting function:
region_of_interest.fort <- fortify(region_of_interest, region = "score")
region_of_interest.fort$id <- as.numeric(region_of_interest.fort$id)
region_of_interest.fort$id <- region_of_interest.fort$id
region_of_interest.fort1 <- fortify(region_of_interest, region = "GM_NAAM")
region_of_interest.fort1$id <- as.character(region_of_interest.fort1$id)
region_of_interest.fort1$id <- region_of_interest.fort1$id
idList <- unique(region_of_interest.fort1$id)
centroids.df <- as.data.frame(coordinates(region_of_interest))
names(centroids.df) <- c("Longitude", "Latitude")
randomMap.df <- data.frame(id = idList, shading = runif(length(idList)), centroids.df)
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
It gives me the error: ggplot2 doesn't know how to deal with data of class uneval
My data
region_of_interest$GM_NAAM
[1] Groningen Haren Ooststellingwerf Assen Aa en Hunze Borger- Odoorn
[7] Noordenveld Westerveld Tynaarlo Midden-Drenthe
415 Levels: 's-Gravenhage 's-Hertogenbosch Aa en Hunze Aalburg Aalsmeer Aalten ... Zwolle
region_of_interest$score
[1] 10 -2 -1 2 -1 -4 -4 -5 0 0
Try something like this?
Get a data frame of the centroids of your polygons from the
original map object.
In the data frame you are plotting, ensure there are columns for
the ID you want to label, and the longitude and latitude of those
centroids.
Use geom_text in ggplot to add the labels.
Based on this example I read a world map, extracting the ISO3 IDs to use as my polygon labels, and make a data frame of countries' ID, population, and longitude and latitude of centroids. I then plot the population data on a world map and add labels at the centroids.
library(rgdal) # used to read world map data
library(rgeos) # to fortify without needing gpclib
library(maptools)
library(ggplot2)
library(scales) # for formatting ggplot scales with commas
# Data from http://thematicmapping.org/downloads/world_borders.php.
# Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
# Unpack and put the files in a dir 'data'
worldMap <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Change "data" to your path in the above!
worldMap.fort <- fortify(world.map, region = "ISO3")
# Fortifying a map makes the data frame ggplot uses to draw the map outlines.
# "region" or "id" identifies those polygons, and links them to your data.
# Look at head(worldMap#data) to see other choices for id.
# Your data frame needs a column with matching ids to set as the map_id aesthetic in ggplot.
idList <- worldMap#data$ISO3
# "coordinates" extracts centroids of the polygons, in the order listed at worldMap#data
centroids.df <- as.data.frame(coordinates(worldMap))
names(centroids.df) <- c("Longitude", "Latitude") #more sensible column names
# This shapefile contained population data, let's plot it.
popList <- worldMap#data$POP2005
pop.df <- data.frame(id = idList, population = popList, centroids.df)
ggplot(pop.df, aes(map_id = id)) + #"id" is col in your df, not in the map object
geom_map(aes(fill = population), colour= "grey", map = worldMap.fort) +
expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) +
scale_fill_gradient(high = "red", low = "white", guide = "colorbar", labels = comma) +
geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
labs(x = "Longitude", y = "Latitude", title = "World Population") +
theme_bw()
Minor technical note: actually coordinates in the sp package doesn't quite find the centroid, but it should usually give a sensible location for a label. Use gCentroid in the rgeos package if you want to label at the true centroid in more complex situations like non-contiguous shapes.
The accepted answer here may work, but the actual question asked specifically notes that there is an error "ggplot2 doesn't know how to deal with data of class uneval."
The reason that it is giving you the error is because the inclusion of centroids.df needs to be a named variable (e.g. accompanied by "data=")
Currently:
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
Should be (note: "data=centroids.df"):
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(data=centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
This issue was addressed here: How to deal with "data of class uneval" error from ggplot2?

Resources