ggplot2 映射数据并使用散列(阴影)方块遮盖子区域,同时保留边界

ggplot2 mapping data and mask sub regions with hashed (shadow) square while preserve borders

这是我正在尝试做的事情:

  1. 我有两个用于 IL 的数据框(例如),每个数据框都有一列来指示县是否应该屏蔽。
  2. 我将使用 facet_wrap() 并排映射这两个数据框,并使用我自己创建的颜色条,从蓝色到红色,均值设置为白色。
  3. 对于 mask=1 的县,我需要屏蔽这些县。

我的问题是:

  1. 我现在用的是灰色遮罩区域,但是非常难看。我看到一些已发表的论文使用带有线条(如阴影区域)的白色背景方块进行遮蔽。我不知道如何称呼它,所以我什至不知道如何 google 搜索它。如果可以使用图例,我应该如何创建遮罩层并为其放置一个单独的图例而不是单个颜色条? 传说是这样的:
  2. 我创建了一个名为 df_mask 的单独数据框,基本上是用 mask=1 挑选出行。然后使用 geom_polygon 绘制该数据框。这是避免这样做的方法吗?因为我的数据框中已经有一列 mask 。比如离散填充,0为透明,1为阴影区域
  3. 现在我的遮蔽层也遮蔽了县之间的边界,这就是为什么我设置 alpha=0.9 这样我可以看到更广阔的地方,但是,那太丑了......我想遮蔽县不掩盖更广泛的。

这是生成当前图的示例代码:

library(RColorBrewer)
library(dplyr)
library(gridExtra)
library(ggplot2)
library(maptools)
library(ggmap)
library(RColorBrewer)
library(colorRamps)
map_il = map_data('county','illinois')
head(map_il)
#create a fake data to plot
counties = unique(map_il$subregion)
n=length(counties)
#fake data 1
df1 = data.frame(subregion=counties, value=runif(n),id=1,mask=sample(0:1,n,TRUE))
df2 = data.frame(subregion=counties, value=runif(n),id=2,mask=sample(0:1,n,TRUE))
merged_df_1 = merge(map_il,df1,sort=FALSE,by='subregion')
merged_df_1 = merged_df_1[order(merged_df_1$order),]
merged_df_2 = merge(map_il,df2,sort=FALSE,by='subregion')
merged_df_2 = merged_df_2[order(merged_df_2$order),]
#set the two df to plot, using facet_wrap and id to seperate
df = rbind(merged_df_1,merged_df_2)
dim(df)
head(df)
#Choose my own color scale, I want the color from blue to red, with white
#stands for the mean of the two plots
get_color = function(c_v){
  return(rgb(c_v[1], c_v[2], c_v[3]))
}
get_color_vector = function(z_min,z_max,z_mean,green_lim=NA){
  #nin <- 256
  nin <- 1000
  nzero <- floor(1 + nin*(z_mean - z_min)/(z_max-z_min))
  maxblue <- .7
  maxred  <- .7

  colors <- matrix(NA, nin, 3)
  colors[1:nzero,3] <- 1
  colors[1:nzero,2] <- seq(1 - maxblue, 1, length.out = nzero)
  colors[1:nzero,1] <- colors[1:nzero,2]
  ix <- (nzero+1):nin
  colors[ix, 1] <- 1
  colors[ix, 2] <- seq(1, 1 - maxred, length.out = nin - nzero)
  colors[ix, 3] <- colors[ix, 2]
  if(!is.na(green_lim)){
    colors[,2] <- seq(green_lim[1],green_lim[2], length.out = nin)
  }
  col_vector <- apply(colors, 1, get_color)
  return(col_vector)                 
}
avg = mean(c(df1$value, df2$value))
r_min = min(c(df1$value, df2$value)) 
r_max = max(c(df1$value, df2$value))
color_vector = get_color_vector(r_min, r_max, avg)
#creat another data frame to make
df_mask = df[df$mask==1,]
#make the plot
qplot(long, lat, data = df, group = group, fill = value,
                  geom = "polygon")+
    scale_fill_gradientn("",colours=color_vector,limits=c(r_min,r_max),
                         breaks=c(r_min,avg,r_max),
                         labels=c(round(r_min),"Avg",round(r_max)))+
    labs(fill='',x="",y="")+
    ggtitle('Sample plot')+
    theme_bw()+facet_wrap(~id,ncol=2)+
    geom_path( data = df , colour = "black")+
    geom_polygon(data=df_mask,fill='grey',alpha=0.9)+
    theme(plot.title = element_text(size=12),
          strip.text.x = element_text(size = 8, colour = "black", angle = 0),
          legend.text = element_text(size=6))

示例图:

问题 1

据我所知,ggplot2 不支持孵化,尽管如果您搜索的话可能会有一些 hacks/tricks 在线。

问题 2

我会在必要时使用您的 mask 列将 value 设置为 NA。对于那些县,您可以设置单独的颜色,不需要第二个 data.frame。你可以用scale_fill_gradientn里面的na.value来控制那个颜色,默认是深灰色。

问题 3

你应该调换图层的顺序。先绘制多边形,然后绘制边界。

一般提示

一般来说,对于像这样更复杂的情节,我总是会使用 ggplot 而不是 qplot

您可能想使用 coord_map 来确保纵横比合理。

代码

df$value[df$mask == 1] <- NA

ggplot(df, aes(long, lat, group = group, fill = value)) +
  geom_polygon() +
  geom_path(data = df , colour = "black") +
  scale_fill_gradientn("",
                       colours = color_vector,
                       limits = c(r_min, r_max),
                       breaks = c(r_min, avg,r_max),
                       labels = c(round(r_min), "Avg", round(r_max)),
                       na.value = 'grey80')+
  labs(x = "", y = "") +
  facet_wrap(~id, ncol = 2) +
  ggtitle('Sample plot') +
  theme_bw() +
  theme(plot.title = element_text(size = 12),
        strip.text.x = element_text(size = 8, colour = "black", angle = 0),
        legend.text = element_text(size = 6)) +
  coord_map()

结果