ika*_*sky 6 r ggplot2 gridextra
ggplot挑战我使用具有固定色标的地图在两个时刻比较变量的空间分布 - 以显示实际变化.将图例条附近的变量分布添加为抖动点会非常好.
所需的绘图应该看起来像图片:假设的红色抖动点是手动添加(我只是使用paint.net)到生成的图R.
要重现地图,需要R调用一个对象fortIT.这是ggplot2::fortify附加数据的意大利NUTS-2区域的强化(使用)SpatialPolygonsDataFrame.该RDATA文件可以下载这里 [89KB]
以及地图的代码:
require(dplyr)
require(ggplot2)
require(ggthemes)
require(gridExtra)
require(rgeos)
require(maptools)
require(cowplot)
require(viridis)
# load the data
load(url("https://ikashnitsky.github.io/share/1602-so-q-map-jitter/fortIT.RData"))
# produce the first map
gIT1 <- ggplot()+
geom_polygon(data = fortIT, aes(x=long, y=lat, group=group, fill=tsr03),
color='grey30',size=.1)+
scale_fill_viridis('TSR\n2003',limits=range(fortIT[,9:10]))+ # !!! limits fix the color scale
coord_equal(xlim=c(4000000, 5500000), ylim=c(1500000,3000000))+
guides(fill = guide_colorbar(barwidth = 1.5, barheight = 15))+
theme_map()+
theme(panel.border=element_rect(color = 'black',size=.5,fill = NA),
legend.position = c(1, 1),
legend.justification = c(1, 1),
legend.background = element_rect(colour = NA, fill = NA),
legend.title = element_text(size=15),
legend.text = element_text(size=15))+
scale_x_continuous(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0)) +
labs(x = NULL, y = NULL)
# produce the second map
gIT2 <- ggplot()+
geom_polygon(data = fortIT, aes(x=long, y=lat, group=group, fill=tsr43),
color='grey30',size=.1)+
scale_fill_viridis('TSR\n2043',limits=range(fortIT[,9:10]))+
coord_equal(xlim=c(4000000, 5500000), ylim=c(1500000,3000000))+
guides(fill = guide_colorbar(barwidth = 1.5, barheight = 15))+
theme_map()+
theme(panel.border=element_rect(color = 'black',size=.5,fill = NA),
legend.position = c(1, 1),
legend.justification = c(1, 1),
legend.background = element_rect(colour = NA, fill = NA),
legend.title = element_text(size=15),
legend.text = element_text(size=15))+
scale_x_continuous(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0)) +
labs(x = NULL, y = NULL)
# align both maps side by side
gIT <- plot_grid(gIT1,gIT2,ncol=2,labels=LETTERS[1:2],label_size=20)
ggsave('italy.png',gIT,width=12,height=7,dpi=192)
Run Code Online (Sandbox Code Playgroud)
地图中可视化的变量是2003年的总支持比率(图A)和2043(图B,欧盟统计局区域预测).总支持率是工作年龄人口(15-64岁)与非工作年龄人口(15 岁以下和65岁以上)的比率.
您可以使用密度信息将图例替换为粘贴有图表面板的图例,
g <- ggplotGrob(p)
leg = gtable_filter(g, "guide-box")
dd <- ddply(fortIT, "group", summarise, fill=unique(tsr03))
dum <- ggplot(dd, aes(0,y=fill)) +
geom_dotplot(fill="red", binaxis = "y", dotsize=0.5, stackdir = "down")+
scale_y_continuous(lim=range(fortIT[,c("tsr03", "tsr43")]), expand=c(0,0)) +
theme_void()
dummy_panel <- gtable_filter(ggplotGrob(dum), "panel")
dummy_panel$layout$clip <- FALSE
a <- leg[[1]][[1]][[1]][[1]]
a <- gtable_add_cols(a, unit(1,"cm"), 0)
a <- gtable_add_grob(a, dummy_panel, 4, 1)
a$layout$clip <- FALSE
grid.newpage()
grid.draw(a)
leg[[1]][[1]][[1]][[1]] <- a
g$grobs[g$layout$name=="guide-box"] <- list(leg)
library(grid)
grid.newpage()
grid.draw(g)
Run Code Online (Sandbox Code Playgroud)
每当需要自定义图例时,我发现最好将图例绘制为单独的图,然后组合。
例如,我们可以定义以下函数:
plot_legend <- function(dots, limits, title, bins = 20) {
n <- 100
tiles <- data.frame(x = rep(0.5, n),
y = seq(limits[1], limits[2], length.out = n))
ggplot() +
geom_raster(data=tiles, aes(x = x, y = y, fill = y), interpolate = TRUE) +
geom_dotplot(data = data.frame(x = dots), aes(x = -.05, y = x, fill = ..y..),
stackdir = "down", binaxis = "y", binwidth = diff(limits)/bins, dotsize = .8) +
scale_x_continuous(limits = c(-5, 1), expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0), position = "right") +
ggtitle(title) +
theme_cowplot(12) +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.line = element_blank(),
axis.title = element_blank(),
plot.title = element_text(face = "plain", hjust = 1),
legend.position = "none")
}
Run Code Online (Sandbox Code Playgroud)
我们可以这样使用:
require(ggplot2)
require(cowplot)
require(viridis)
dots <- 3*runif(100)
range <- c(0, 3)
plot_legend(dots, range, "random numbers") + scale_fill_viridis()
Run Code Online (Sandbox Code Playgroud)
现在我们将其与地图代码一起使用。它需要对图例在人物中的最终位置进行一些调整,但并不太复杂。
require(dplyr)
load(url("https://ikashnitsky.github.io/misc/160227-SO-question/fortIT.RData"))
# extract tsr03 and tsr43 data
fortIT %>% group_by(group) %>%
summarize(tsr03 = tsr03[1], tsr43 = tsr43[1]) -> df_tsr
# get color range limits
limits <- range(fortIT[,9:10])
# make the legends
legIT1 <- plot_legend(df_tsr$tsr03, limits, "TSR 2003") + scale_fill_viridis()
legIT2 <- plot_legend(df_tsr$tsr43, limits, "TSR 2043") + scale_fill_viridis()
# produce the first map
gIT1 <- ggplot()+
geom_polygon(data = fortIT, aes(x=long, y=lat, group=group, fill=tsr03),
color='grey30', size=.1) +
scale_x_continuous(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0)) +
scale_fill_viridis('TSR\n2003', limits = limits, guide = "none") +
coord_equal(xlim=c(4000000, 5500000), ylim=c(1500000, 3000000)) +
theme_map() +
theme(panel.border=element_rect(color = 'black',size=.5,fill = NA))
# produce the second map
gIT2 <- ggplot()+
geom_polygon(data = fortIT, aes(x=long, y=lat, group=group, fill=tsr43),
color='grey30',size=.1)+
scale_x_continuous(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0)) +
scale_fill_viridis('TSR\n2043', limits = limits, guide = "none") +
coord_equal(xlim=c(4000000, 5500000), ylim=c(1500000, 3000000)) +
theme_map() +
theme(panel.border=element_rect(color = 'black',size=.5,fill = NA))
# put everything together
plot_grid(ggdraw(gIT1) + draw_plot(legIT1, .62, .35, .35, .55),
ggdraw(gIT2) + draw_plot(legIT2, .62, .35, .35, .55),
ncol=2, labels="AUTO")
Run Code Online (Sandbox Code Playgroud)
两条评论:
堆叠点的大小可以通过函数bins的参数来控制plot_legend()。越大bins,点越小。
我通常会删除每张地图周围的框架,但我在这里尝试尽可能接近地重现原始图形。