linked micromaps

43 views
Skip to first unread message

mgm

unread,
Jul 8, 2011, 3:06:17 PM7/8/11
to ggplot2
Does anyone know if ggplot2 has been used to produced linked
micromaps?
Thanks

Brian Diggs

unread,
Jul 11, 2011, 5:36:52 PM7/11/11
to mgm, ggplot2

I don't know of anyone who has and a quick Google search didn't turn up
anything. I looked at what sort of characteristics they have to see if
they fit well in the ggplot2 framework. The documentation and examples
at
http://gis.cancer.gov/tools/micromaps/help/WebHelp/Linked_Micromaps.htm#Graph_Examples.htm
was handy.

The idea of small multiples and faceting (what you see going down a
column) is pretty deeply embedded in ggplot2. But completely different
types of plots going across breaks the faceting assumptions. Looking at
Figure 24 as an example, it is small multiples of 5 counties at a time
going down. Order is determined by the value of one of the data
variables. All that is doable. But the first column is effectively a
color legend, the second is a map, and the third is a dot (or dot with
confidence intervals) plot and the fourth is a dot plot. If it were
just the last two, it would be easy because they share a y-axis.
However, that would not have the micromaps which is the unique part.

You can cobble something together, and with some work it probably would
look pretty good. With some more work, it might even be
parametrizable/automatable. Here is some rough sketches to show the
direction something like this might work:

library("ggplot2")
library("maps")

# Get Maryland county shapes
data(countyMapEnv)
md <- map_data(map="county", region="maryland")
md.counties <- unique(md$subregion)

# Create some fake data for the ranking of counties
md.df <- data.frame(county=md.counties,
rate=sample(40:80, length(md.counties), replace=TRUE))
md.df <- md.df[rev(order(md.df$rate)),]
md.df$rank <- 1:nrow(md.df)

#group by 5's
md.df <- transform(md.df,
grouping = ((rank-1) %/% 5) + 1,
in.group.pos = ((rank-1) %% 5) + 1,
county = factor(county, levels=rev(county)))

# Make the rate plot; colour is controlled by the position in group
# variable, so the colors get recycled across facets.
ranks.plot <-
ggplot(md.df) +
geom_point(aes(x=rate, y=county, colour=factor(in.group.pos))) +
facet_wrap(~grouping, ncol=1, scales="free_y") +
scale_colour_manual(values=c("red", "orange", "green", "blue",
"purple"), legend = FALSE) +
opts(strip.background = theme_blank(), strip.text.x = theme_blank())

# Make the data needed for the micromaps
md2 <- merge(md, md.df, by.x="subregion", by.y="county")
md2 <- md2[order(md2$order),]

# Coloring the counties that appeared previously was tricky;
# this dataset associates with each grouping all the counties
# that are in a smaller numbered group.
md2.lesser <- ddply(data.frame(grouping=unique(md2$grouping)),
.(grouping),
function(x) {
ttt <- md2[md2$grouping < x$grouping,]
ttt$grouping <- NULL
ttt
})

# The micromaps plot
counties.plot <-
ggplot(md2, aes(x=long, y=lat, group=group)) +
geom_polygon(fill=NA, colour="black", data=transform(md2,
grouping=NULL, in.group.pos=NULL)) +
geom_polygon(fill="gray80", colour="black", data=md2.lesser) +
geom_polygon(aes(fill=factor(in.group.pos)), colour="black") +
scale_fill_manual(values=c("red", "orange", "green", "blue",
"purple"), legend = FALSE) +
facet_wrap(~grouping, ncol=1) +
coord_map() +
opts(strip.background = theme_blank(), strip.text.x = theme_blank(),
panel.background = theme_blank(), panel.grid.major =
theme_blank(),
panel.grid.minor = theme_blank(), axis.text.x = theme_blank(),
axis.text.y = theme_blank(), axis.title.x = theme_blank(),
axis.title.y = theme_blank(), axis.line = theme_blank(),
axis.ticks = theme_blank()
)

# These two plots are disjoint; they can't be faceted because they are
# not the same type. Using ideas from ggExtra::align.plots to compose
# these next to each other.
grid.newpage()
vp <- viewport(layout = grid.layout(ncol = 2))
pushViewport(vp)
pushViewport(viewport(layout.pos.col = 1))
grid.draw(ggplotGrob(counties.plot))
upViewport(1)
pushViewport(viewport(layout.pos.col = 2))
grid.draw(ggplotGrob(ranks.plot))
upViewport(1)

# Alignment is not quite right (because on has a bottom axis and
# the other doesn't, but that might be tweakable with the theme).
# Also, the color "legend" would probably have to be built as its
# own set of faceted plots (drawing the filled squares and adding the
# text). The ranks along the left of the plots are in the position of
# axis labels, but are really meant to carry different information;
# the y-axis "labels" are in the first column as part of the aligned
# "legend". You probably get something like this using the
# discrete scale labelling to make the label the rank (rather than
# the name); this is somewhat abusing the notion (and would require
# each data plot to be separate and stuck together at the end since
# they wouldn't share a common "scale")

# I've gone far enough that I am fairly sure that something fairly
# good looking could be made using ggplot2, but there are still a lot
# of details that would need to be worked out. I'll leave that to
# someone who actually needs a plot like this.


--
Brian S. Diggs, PhD
Senior Research Associate, Department of Surgery
Oregon Health & Science University

Reply all
Reply to author
Forward
0 new messages