Choropleth Map in Ggplot with Polygons That Have Holes

Choropleth map in ggplot with polygons that have holes

You can plot the island polygons in a separate layer, following the example on the ggplot2 wiki. I've modified your merging steps to make this easier:

mrg.df <- data.frame(id=rownames(map@data),ID_1=map@data$ID_1)
mrg.df <- merge(mrg.df,pov, by="ID_1")
map.df <- fortify(map)
map.df <- merge(map.df,mrg.df, by="id")

ggplot(map.df, aes(x=long, y=lat, group=group)) +
geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+
geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, Id1 %in% c("Berlin", "Bremen")))+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+
labs(x="",y="")+ theme_bw()+
coord_fixed()

map of germany

As an unsolicited act of evangelism, I encourage you to consider something like

library(ggmap)
qmap("germany", zoom = 6) +
geom_polygon(aes(x=long, y=lat, group=group, fill=poverty),
color = "grey50", alpha = .7,
data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+
geom_polygon(aes(x=long, y=lat, group=group, fill=poverty),
color = "grey50", alpha= .7,
data =subset(map.df, Id1 %in% c("Berlin", "Bremen")))+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))

to provide context and familiar reference points.

Plot ggplot polygons with holes with geom_polygon

My temporary solution is: @#$% polygons, and use the raster package.

Namely:

r <- raster(x=extent(r3.pol), crs=crs(r3.pol)) # empty raster from r3.pol
res(r) <- 250 # set a decent resolution (depends on your extent)
r <- setValues(r, 1) # fill r with ones
r <- mask(r, r3.pol) # clip r with the shape polygons

And now plot it as you would do with any raster with ggplot. The rasterVis package might come helpful here, but I'm not using it, so:

rdf <- data.frame(rasterToPoints(r))
p <- ggplot(rdf) + geom_raster(mapping=aes(x=x, y=y), fill='red')
p <- p + coord_equal()

And here it goes.

Sample Image

Alternatively, you can create the raster with rasterize, so the raster will hold the polygons values (in my case, just an integer):

r <- raster(x=extent(r3.pol), crs=crs(r3.pol))
res(r) <- 250
r <- rasterize(r3.pol, r)

rdf <- data.frame(rasterToPoints(r))
p <- ggplot(rdf) + geom_raster(mapping=aes(x=x, y=y, fill=factor(layer)))
p <- p + coord_equal()

Sample Image

If someone comes up with a decent solution for geom_polygon, probably involving re-ordering of the polygons data frame, I'll be glad to consider it.

Use ggplot to plot polygon with holes (in a city map)

One common convention to draw polygons with holes is:

  • A closed polygon with points that progress anti-clockwise forms a solid shape
  • A closed polygon with points progressing clockwise forms a hole

So, let's construct some data and plot:

library(ggplot2)

ids <- letters[1:2]

# IDs and values to use for fill colour
values <- data.frame(
id = ids,
value = c(4,5)
)

# Polygon position
positions <- data.frame(
id = rep(ids, each = 10),
# shape hole shape hole
x = c(1,4,4,1,1, 2,2,3,3,2, 5,10,10,5,5, 6,6,9,9,6),
y = c(1,1,4,4,1, 2,3,3,2,2, 5,5,10,10,5, 6,9,9,6,6)
)

# Merge positions and values
datapoly <- merge(values, positions, by=c("id"))

ggplot(datapoly, aes(x=x, y=y)) +
geom_polygon(aes(group=id, fill=factor(value))) +
scale_fill_discrete("Key")

Sample Image

Region polygons not displaying in ggplot2 Choropleth map

Your problem is very simple. Change

colnames(ghaDF[5])<-"id"

to

colnames(ghaDF)[5]<-"id"

and your code produces the map you want.

The first line above extracts column 5 of ghaDF as a data frame with 1 column, sets that column name to "id", and discards it when the call to colnames(...) completes. It does not affect the original data frame at all.

The second line extracts the column names of ghaDF as a character vector, and sets the 5th element of that vector to "id", which in effect changes the name of column 5 of ghaDF.

Having said all this, your workflow is a bit tortured. For one thing you are merging all the columns of gadm@data into ghaMap, which is unnecessary and extremely inefficient. The code below produces the same map:

load(url("http://biogeo.ucdavis.edu/data/gadm2/R/GHA_adm1.RData"))
ghaMap <- fortify(gadm)
ghaDF <- data.frame(id=rownames(gadm@data),
prod=c(12,26,12,22,0,11,4,5,4,4))
ghaMap <- merge(ghaMap,ghaDF)
ggplot(ghaMap, aes(x=long,y=lat,group=group))+
geom_polygon(aes(fill=prod))+
geom_path(color="gray")+
scale_fill_gradient(low = "light green", high = "dark green")+
coord_map()

Sample Image

Avoiding hoizontal lines and crazy shapes when plotting maps in ggplot2

Sample ImageThe other solution is to restrict the view, rather than remove point from the render:

library(ggplot2)
library(maptools)
library(mapproj)

# Maptools dataset
data(wrld_simpl)
world <- fortify(wrld_simpl)

# Same plot, but restrict the view instead of removing points
# allowing the complete render to happen
ggplot(world, mapping = aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "black", colour = "black") +
coord_cartesian(xlim = c(-125, -30), ylim = c(-60, 35))

ggplot US state map; colors are fine, polygons jagged - r

You don't need to do the merge. You can use geom_map and keep the data separate from the shapes. Here's an example using the built-in USArrests data (reformatted with dplyr):

library(ggplot2)
library(dplyr)

us <- map_data("state")

arr <- USArrests %>%
add_rownames("region") %>%
mutate(region=tolower(region))

gg <- ggplot()
gg <- gg + geom_map(data=us, map=us,
aes(x=long, y=lat, map_id=region),
fill="#ffffff", color="#ffffff", size=0.15)
gg <- gg + geom_map(data=arr, map=us,
aes(fill=Murder, map_id=region),
color="#ffffff", size=0.15)
gg <- gg + scale_fill_continuous(low='thistle2', high='darkred',
guide='colorbar')
gg <- gg + labs(x=NULL, y=NULL)
gg <- gg + coord_map("albers", lat0 = 39, lat1 = 45)
gg <- gg + theme(panel.border = element_blank())
gg <- gg + theme(panel.background = element_blank())
gg <- gg + theme(axis.ticks = element_blank())
gg <- gg + theme(axis.text = element_blank())
gg

Sample Image



Related Topics



Leave a reply



Submit