ggplot2:在图例栏附近添加分布抖动
ggplot2: add distribution jitter near the legend bar
一个不平凡的 ggplot
挑战
我使用具有固定色标的地图比较变量在两个时刻的空间分布 - 以显示实际变化。最好将图例条附近的变量分布添加为抖动点。
所需的图应该看起来像图片:假设的 red 抖动点是手动添加的(我刚刚使用 paint.net)到 [= 生成的图12=].
复制地图
要复制地图,需要一个名为 fortIT
的 R
对象。这是一个强化的(使用 ggplot2::fortify
)意大利 NUTS-2 区域的 SpatialPolygonsDataFrame,附有数据。 RData文件可以下载here[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)
附加信息
地图中可视化的变量是 2003 年(面板 A)和 2043 年(面板 B,欧盟统计局区域预测)的总支持率。总支持率是工作年龄人口(15-64 岁)与非工作年龄人口(15 岁以下和 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)
每当需要自定义图例时,我发现最好将图例绘制为单独的图,然后再合并。
例如,我们可以定义如下函数:
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")
}
我们可以这样使用:
require(ggplot2)
require(cowplot)
require(viridis)
dots <- 3*runif(100)
range <- c(0, 3)
plot_legend(dots, range, "random numbers") + scale_fill_viridis()
现在我们将其与地图代码一起使用。需要对图例的最终位置进行一些调整,但并不过分复杂。
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")
两条评论:
堆叠点的大小可以通过plot_legend()
函数的bins
参数来控制。 bins
越大点越小
我通常会删除每张地图周围的边框,但我在这里尝试尽可能接近地重现原始图形。
一个不平凡的 ggplot
挑战
我使用具有固定色标的地图比较变量在两个时刻的空间分布 - 以显示实际变化。最好将图例条附近的变量分布添加为抖动点。
所需的图应该看起来像图片:假设的 red 抖动点是手动添加的(我刚刚使用 paint.net)到 [= 生成的图12=].
复制地图
要复制地图,需要一个名为 fortIT
的 R
对象。这是一个强化的(使用 ggplot2::fortify
)意大利 NUTS-2 区域的 SpatialPolygonsDataFrame,附有数据。 RData文件可以下载here[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)
附加信息
地图中可视化的变量是 2003 年(面板 A)和 2043 年(面板 B,欧盟统计局区域预测)的总支持率。总支持率是工作年龄人口(15-64 岁)与非工作年龄人口(15 岁以下和 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)
每当需要自定义图例时,我发现最好将图例绘制为单独的图,然后再合并。
例如,我们可以定义如下函数:
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")
}
我们可以这样使用:
require(ggplot2)
require(cowplot)
require(viridis)
dots <- 3*runif(100)
range <- c(0, 3)
plot_legend(dots, range, "random numbers") + scale_fill_viridis()
现在我们将其与地图代码一起使用。需要对图例的最终位置进行一些调整,但并不过分复杂。
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")
两条评论:
堆叠点的大小可以通过
plot_legend()
函数的bins
参数来控制。bins
越大点越小我通常会删除每张地图周围的边框,但我在这里尝试尽可能接近地重现原始图形。