ggplot 在一个图例中使用 "colour" 和 "fill" 作为 astetic 到同一时间
ggplot with different types in one legend by using "colour" and "fill" as astetic to same time
我在 ggplot 中绘制图例时遇到问题。我已经在网上搜索了几个小时来寻找解决方案,但还没有找到任何解决方案。
我正在尝试使用不同的线和多边形 shapefile 创建一个 ggplot。我使用函数 geom_sf() 绘制 shapefile。画图不是问题。我的问题与图例创建有关。
目标是创建一个具有单一图例并具有所有不同 shapefile 类型的图,包括它们的颜色和/或填充 astetic。这意味着,线形在图例中应表示为简单的线,多边形应表示为简单的多边形。这些我都做到了。
主要困难在于其中一个 polygonshape(为了更好的可读性)不仅使用“填充”参数作为 astetic,还使用“颜色”参数。
如果我创建一个绘图,其中所有多边形始终使用填充参数作为 astetic,所有线形始终使用 color 参数作为 astetic,一切正常。但是,一旦我在同时使用两个参数的图中包含一个多边形形状,它就会破坏整个图例结构。在这种情况下,例如,线条 shapefile 的符号突然有一个框架 and/or 背景,尽管它们不应该有一个。
用 ggplot 构建这样的东西是不可能的还是我只是笨拙?
总结:
类似于下面创建的最小示例,我想在此图中创建一个图例,其中:
- A = 多边形符号没有边框(如
情节)
- B = 带边框的多边形符号(如图所示)并且
- C = 一条没有边框或背景的简单线条(如图中所示)。
如何让它工作?
library(ggplot2)
library(sf)
poly1 <- cbind(lon = c(5, 6, 7, 5), lat = c(52, 53, 51, 52))
poly2 <- cbind(lon = c(3, 5, 7, 3), lat = c(50, 52, 50, 50))
poly1 <- st_sf(st_sfc(st_polygon(list(poly1))))
poly2 <- st_sf(st_sfc(st_polygon(list(poly2))))
line <- st_sf(st_sfc(list(st_linestring(cbind(lon = c(5.5, 4.5), lat = c(53.5, 54.5))))))
ggplot() +
geom_sf(data = poly1,
aes(fill = "A"),
colour = NA,
show.legend = "polygon") +
geom_sf(data = poly2,
aes(fill = "B",
colour = "B"),
show.legend = "polygon") +
geom_sf(data = line,
aes(colour = "C"),
show.legend = "line") +
scale_fill_manual(name="Legend",
values = c("A" = "yellow", "B" = "green"),
guide = guide_legend(override.aes = list(linetype = c("blank","blank"), shape = NA))
) +
scale_colour_manual(name="Legend",values = c("B" = "blue", "C" = "purple"),
guide = guide_legend(override.aes = list(linetype = c(0, 1)))) +
theme_bw()
您可以使用 ggnewscale
并为每个 geom 层设置键字形来做到这一点:
ggplot() +
geom_sf(data = poly1,
aes(fill = "A"),
colour = NA,
key_glyph = "rect") +
scale_fill_manual(values = "yellow", name = NULL,
guide = guide_legend(order = 1)) +
ggnewscale::new_scale_fill() +
ggnewscale::new_scale_color() +
geom_sf(data = poly2,
aes(fill = "B",
colour = "B"),
key_glyph = "polygon") +
scale_color_manual(values = "blue", name = NULL,
guide = guide_legend(order = 2)) +
scale_fill_manual(values = "green", name = NULL,
guide = guide_legend(order = 2)) +
ggnewscale::new_scale_color() +
geom_sf(data = line,
aes(colour = "C"),
key_glyph = "path") +
scale_colour_manual(values = "purple", name = NULL,
guide = guide_legend(order = 3)) +
theme_bw()
我也喜欢@AllanCameron 的回答,但这里有一种方法可以在没有 ggnewscale
.
的情况下做同样的事情
你总共有三把钥匙。对于 A 和 B,它们都应该表示为多边形,但是 B 应该有一个边框和A不应该。 C 是奇数,因为它应该在图例中由一个单独的符号表示。
因此,这里的做法是让A和B属于同一个图例(一个来自color=
的组合)和 fill=
),并将 C 保留在单独的图例中。
对于A和B,我在aes()
中指定了fill=
和color=
两者,然后使用 scale_*_manual()
函数为两者锻炼颜色。
如果您在 aes()
内将 color=
分配给 C,您将强制 ggplot2
使用 [= 将其推入图例46=]A 和 B。这意味着我们需要在不同的审美下为 C 指定图例!在这种情况下,我使用 alpha=
,但同样适用于 linetype
、size
等
p <-
ggplot() +
geom_sf(
data = poly1, aes(fill = "A", colour = "A")) +
geom_sf(
data = poly2, aes(fill = "B", colour = "B")) +
geom_sf(
data = line, aes(alpha = "C"), colour = "purple") +
scale_fill_manual(
name="Legend", values = c("A" = "yellow", "B" = "green")) +
scale_colour_manual(
name="Legend", values = c("A" = "transparent", "B" = "blue", "C" = "purple")) +
scale_alpha_manual(name=NULL, values=1) +
guides(
fill=guide_legend(order=1, override.aes = list(linetype = c(0,1))),
colour= "none"
) +
theme_bw()
p
为了使图例彼此更接近,您可以通过 theme()
指定 legend.spacing
。你必须玩弄这个数字,但它有效。在这种情况下,使 legend.background
透明也很重要,因为图例相互夹在一起。
p + theme(
legend.background = element_rect(fill=NA),
legend.spacing = unit(-15, "pt")
)
我在 ggplot 中绘制图例时遇到问题。我已经在网上搜索了几个小时来寻找解决方案,但还没有找到任何解决方案。
我正在尝试使用不同的线和多边形 shapefile 创建一个 ggplot。我使用函数 geom_sf() 绘制 shapefile。画图不是问题。我的问题与图例创建有关。
目标是创建一个具有单一图例并具有所有不同 shapefile 类型的图,包括它们的颜色和/或填充 astetic。这意味着,线形在图例中应表示为简单的线,多边形应表示为简单的多边形。这些我都做到了。
主要困难在于其中一个 polygonshape(为了更好的可读性)不仅使用“填充”参数作为 astetic,还使用“颜色”参数。
如果我创建一个绘图,其中所有多边形始终使用填充参数作为 astetic,所有线形始终使用 color 参数作为 astetic,一切正常。但是,一旦我在同时使用两个参数的图中包含一个多边形形状,它就会破坏整个图例结构。在这种情况下,例如,线条 shapefile 的符号突然有一个框架 and/or 背景,尽管它们不应该有一个。
用 ggplot 构建这样的东西是不可能的还是我只是笨拙?
总结:
类似于下面创建的最小示例,我想在此图中创建一个图例,其中:
- A = 多边形符号没有边框(如
情节) - B = 带边框的多边形符号(如图所示)并且
- C = 一条没有边框或背景的简单线条(如图中所示)。
如何让它工作?
library(ggplot2)
library(sf)
poly1 <- cbind(lon = c(5, 6, 7, 5), lat = c(52, 53, 51, 52))
poly2 <- cbind(lon = c(3, 5, 7, 3), lat = c(50, 52, 50, 50))
poly1 <- st_sf(st_sfc(st_polygon(list(poly1))))
poly2 <- st_sf(st_sfc(st_polygon(list(poly2))))
line <- st_sf(st_sfc(list(st_linestring(cbind(lon = c(5.5, 4.5), lat = c(53.5, 54.5))))))
ggplot() +
geom_sf(data = poly1,
aes(fill = "A"),
colour = NA,
show.legend = "polygon") +
geom_sf(data = poly2,
aes(fill = "B",
colour = "B"),
show.legend = "polygon") +
geom_sf(data = line,
aes(colour = "C"),
show.legend = "line") +
scale_fill_manual(name="Legend",
values = c("A" = "yellow", "B" = "green"),
guide = guide_legend(override.aes = list(linetype = c("blank","blank"), shape = NA))
) +
scale_colour_manual(name="Legend",values = c("B" = "blue", "C" = "purple"),
guide = guide_legend(override.aes = list(linetype = c(0, 1)))) +
theme_bw()
您可以使用 ggnewscale
并为每个 geom 层设置键字形来做到这一点:
ggplot() +
geom_sf(data = poly1,
aes(fill = "A"),
colour = NA,
key_glyph = "rect") +
scale_fill_manual(values = "yellow", name = NULL,
guide = guide_legend(order = 1)) +
ggnewscale::new_scale_fill() +
ggnewscale::new_scale_color() +
geom_sf(data = poly2,
aes(fill = "B",
colour = "B"),
key_glyph = "polygon") +
scale_color_manual(values = "blue", name = NULL,
guide = guide_legend(order = 2)) +
scale_fill_manual(values = "green", name = NULL,
guide = guide_legend(order = 2)) +
ggnewscale::new_scale_color() +
geom_sf(data = line,
aes(colour = "C"),
key_glyph = "path") +
scale_colour_manual(values = "purple", name = NULL,
guide = guide_legend(order = 3)) +
theme_bw()
我也喜欢@AllanCameron 的回答,但这里有一种方法可以在没有 ggnewscale
.
你总共有三把钥匙。对于 A 和 B,它们都应该表示为多边形,但是 B 应该有一个边框和A不应该。 C 是奇数,因为它应该在图例中由一个单独的符号表示。
因此,这里的做法是让A和B属于同一个图例(一个来自color=
的组合)和 fill=
),并将 C 保留在单独的图例中。
对于A和B,我在aes()
中指定了fill=
和color=
两者,然后使用 scale_*_manual()
函数为两者锻炼颜色。
如果您在 aes()
内将 color=
分配给 C,您将强制 ggplot2
使用 [= 将其推入图例46=]A 和 B。这意味着我们需要在不同的审美下为 C 指定图例!在这种情况下,我使用 alpha=
,但同样适用于 linetype
、size
等
p <-
ggplot() +
geom_sf(
data = poly1, aes(fill = "A", colour = "A")) +
geom_sf(
data = poly2, aes(fill = "B", colour = "B")) +
geom_sf(
data = line, aes(alpha = "C"), colour = "purple") +
scale_fill_manual(
name="Legend", values = c("A" = "yellow", "B" = "green")) +
scale_colour_manual(
name="Legend", values = c("A" = "transparent", "B" = "blue", "C" = "purple")) +
scale_alpha_manual(name=NULL, values=1) +
guides(
fill=guide_legend(order=1, override.aes = list(linetype = c(0,1))),
colour= "none"
) +
theme_bw()
p
为了使图例彼此更接近,您可以通过 theme()
指定 legend.spacing
。你必须玩弄这个数字,但它有效。在这种情况下,使 legend.background
透明也很重要,因为图例相互夹在一起。
p + theme(
legend.background = element_rect(fill=NA),
legend.spacing = unit(-15, "pt")
)