使用 override.aes 大小时图例键中的 R ggplot2 空格

R ggplot2 whitespace in legend key when using override.aes for size

我最近对与 报道的相同问题感到沮丧,该问题涉及弥补 ggplot 不向图例添加 NA 填充所需的黑客攻击(如果有人知道对此的更新,请告诉我).

因此,我创建了一个类似的 hack,但在一个相当复杂的情节中,我试图同时展示几件事。该图需要将点的大小设置为较小的值,因此我需要 override.aes 在图例中有足够大的点。因为我使用了 alphacolour,所以我将两者都引入了同一个图例键。

然而,奇怪的是(至少对我而言),aes 覆盖在图例键框边距和填充之间创建了难看的空白,如带有和不带有大小 aes 覆盖的地图所示:

这是怎么发生的,我怎样才能让它消失?任何帮助将不胜感激。

这是重现此代码的代码。如前所述,我的真实情节比这更复杂,但这显示了总体思路。

## create an example using the world data
require(rworldmap) 
require(rgeos)
require(ggplot2)
require(viridis)

## Load world map and subset
world <- getMap()
world <- world[!world@data$ADMIN %in% c("French Southern and Antarctic Lands", 
                                        "Heard Island and McDonald Islands",
                                        "French Guiana"),] #NA entries for these in REGION col
world <- world[world@data$REGION == "South America",]

world@data$id = rownames(world@data)

## create example where we have NA for the fill variable
world@data$fillvar <- world@data$LAT
world@data$fillvar[round(world@data$LAT) == -9] <- NA #Peru

## create spatial data frame for plotting
polydf = ggplot2::fortify(world, region="id")
polydf <- merge(polydf, world@data, by="id")

## create arbitrary grouping variable
polydf$groupvar <- ifelse(polydf$NAME == "Bolivia", "Bolivia", "NotBolivia") # the two main classes


# simulate hack where we name the NA fill case as a new grouping level (which we will use alpha for)
polydf$groupvar[is.na(polydf$fillvar)] <- 'Removed' 
polydf$groupvar <- factor(polydf$groupvar)

## create centroid points to show the grouping with points, again manual hack for NA
pointsdf <- gCentroid(world[!is.na(world@data$fillvar),],byid=TRUE)
pointsdf <- as.data.frame(pointsdf@coords)
pointsdf$groupvar <- ifelse(rownames(pointsdf)=="Bolivia","Bolivia","NotBolivia")

pointsNA <- gCentroid(world[is.na(world@data$fillvar),], byid=TRUE)
pointsNA <- as.data.frame(pointsNA@coords)
pointsNA$groupvar <- "Removed"

pointsdf <- rbind(pointsdf, pointsNA)
pointsdf$groupvar <- factor(pointsdf$groupvar)

## plot with override.aes for size
sizeover <- ggplot(polydf) + theme_bw() +
  aes(long,lat,group=group) + 
  geom_polygon(aes(fill=fillvar, alpha=groupvar)) +  # shading also for groupvar
  geom_path(color="black") +
  coord_equal() +
  scale_fill_viridis("Fill", na.value="black") + 
  geom_point(inherit.aes=FALSE, data=pointsdf, aes(x=x, y=y, group=groupvar, col=groupvar), size=1) +
  scale_color_manual('Alpha + colour', values=c("black","transparent","white")) +
  scale_alpha_manual('Alpha + colour', values=c(0.8,0.8, 1)) +
  theme(legend.key = element_rect(colour = "black"), legend.box = "vertical", legend.position = "top") +
  guides(color=guide_legend(override.aes = list(size=2)), 
         alpha=guide_legend(override.aes = list(alpha=c(1,1,1), fill=c('white','white','black'))))

## plot without override.aes for size
nosizeover <- ggplot(polydf) + theme_bw() +
  aes(long,lat,group=group) + 
  geom_polygon(aes(fill=fillvar, alpha=groupvar)) +  # shading also for groupvar
  geom_path(color="black") +
  coord_equal() +
  scale_fill_viridis("Fill", na.value="black") + 
  geom_point(inherit.aes=FALSE, data=pointsdf, aes(x=x, y=y, group=groupvar, col=groupvar), size=1) +
  scale_color_manual('Alpha + colour', values=c("black","transparent","white")) +
  scale_alpha_manual('Alpha + colour', values=c(0.8,0.8, 1)) +
  theme(legend.key = element_rect(colour = "black"), legend.box = "vertical", legend.position = "top") +
  guides(alpha=guide_legend(override.aes = list(alpha=c(1,1,1), fill=c('white','white','black'))))

grid.arrange(sizeover, nosizeover, ncol=2)

两个图(sizeovernosizeover)都存在这个问题,只是前者更明显。有罪的一方是ggplot2中的函数draw_key_polygon()。它根据 size 设置(请参阅 here)在其绘制的矩形周围创建一些 space。我不太清楚为什么要这样写,但大概是有原因的。

最简单的解决方案类似于 将图例绘制功能替换为geom_polygon()。在这种情况下,我们甚至不必自己编写新的,我们可以使用现有的:

GeomPolygon$draw_key <- ggplot2::draw_key_rect
sizeover

这造成的唯一问题是现在图例轮廓看起来有点细,因为填充的矩形绘制在轮廓之上。我们可以通过将线加粗一点来解决这个问题,方法是将其添加到绘图中:

+ theme(legend.key = element_rect(colour = "black", size = 1)) 

这对我来说似乎是一个合理的解决方案。

请注意,geom_polygon() 将在剩余的会话中继续使用修改后的图例绘制功能。要撤消,运行:

GeomPolygon$draw_key <- ggplot2::draw_key_polygon