问题描述
假设我在 ggplot 中有以下图:
Suppose I have the following plot in ggplot:
它是使用以下代码生成的:
It was generated using the code below:
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df.merged <- rbind(df1, df2, df3, df4)
ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
我希望只有一个图例可以正确显示形状、颜色和线条类型(交互(类型、方法)图例与我想要的最接近,但它没有正确的形状/线型).
I would like to have only one legend that correctly displays the shapes, the colors and the line types (the interaction(Type, Method) legends is the closest to what I would like, but it does not have the correct shapes/line types).
我知道如果我使用 scale_xxx_manual 并为所有图例指定相同的标签,它们将被合并,但我不想手动设置标签:如果有新的方法或类型,我不想修改我的代码:想要一些通用的东西.
I know that if I use scale_xxx_manual and I specify the same labels for all legends they will be merged, but I don't want to have to set the labels manually: if there are new Methods or Types, I don't want to have to modify my code: a want something generic.
正如下面的答案所指出的,在这种特殊情况下,有几种方法可以完成工作.所有建议的解决方案都需要使用 scale_xxx_manual 函数
s 或 guides
函数手动设置图例线类型和形状.
As pointed in answers below, there are several ways to get the job done in this particular case. All proposed solutions require to manually set the legend line types and shapes, either by using scale_xxx_manual function
s or with guides
function.
但是,建议的解决方案在一般情况下仍然不起作用:例如,如果我使用新的method3"方法向数据集添加一个新的数据框,它不再起作用,我们必须手动添加新的图例形状和线型:
However, the proposed solutions still don't work in the general case: for instance, if I add a new data frame to the data set with a new "method3" Method, it does not work anymore, we have to manually add the new legend shapes and line types:
y5 <- sin(x - pi / 4)
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
df.merged <- rbind(df1, df2, df3, df4, df5)
override.shape <- c(16, 17, 16, 17, 16)
override.linetype <- c(1, 1, 3, 3, 4)
g <- ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
g <- g + guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype)))
g <- g + scale_shape(guide = FALSE)
g <- g + scale_linetype(guide = FALSE)
print(g)
这给出:
现在的问题是:如何自动生成override.shape
和override.linetype
向量?
Now the question is: how to automatically generate the override.shape
and override.linetype
vectors?
请注意,向量大小为 5,因为我们有 5 条曲线,而 interaction(Type, Method)
因子的大小为 6(我没有 cos/method3 组合的数据)
Note that the vector size is 5 because we have 5 curves, while the interaction(Type, Method)
factor has size 6 (I don't have data for the cos/method3 combination)
推荐答案
以下是一般情况下的解决方案:
Here is the solution in the general case:
# Create the data frames
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
y5 <- sin(x - pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
# Merge the data frames
df.merged <- rbind(df1, df2, df3, df4, df5)
# Create the interaction
type.method.interaction <- interaction(df.merged$Type, df.merged$Method)
# Compute the number of types and methods
nb.types <- nlevels(df.merged$Type)
nb.methods <- nlevels(df.merged$Method)
# Set the legend title
legend.title <- "My title"
# Initialize the plot
g <- ggplot(df.merged, aes(x,
y,
colour = type.method.interaction,
linetype = type.method.interaction,
shape = type.method.interaction)) + geom_line() + geom_point()
# Here is the magic
g <- g + scale_color_discrete(legend.title)
g <- g + scale_linetype_manual(legend.title,
values = rep(1:nb.types, nb.methods))
g <- g + scale_shape_manual(legend.title,
values = 15 + rep(1:nb.methods, each = nb.types))
# Display the plot
print(g)
结果如下:
- 正弦曲线绘制为实线,余弦曲线绘制为虚线.
- method1"数据使用实心圆作为形状.
- method2"数据使用实心三角形作为形状.
- method3"数据使用实心菱形作为形状.
- 图例与曲线匹配
总而言之,技巧是:
- 将类型/方法
interaction
用于所有数据表示(颜色、形状、线型等) - 然后手动设置曲线样式和图例样式
scale_xxx_manual
. scale_xxx_manual
允许您提供比实际曲线数量更长的值向量,因此可以轻松地根据类型和方法因子的大小计算样式向量值
- Use the Type/Method
interaction
for all data representations (colour, shape,linetype, etc.) - Then manually set both the curve styles and the legends styles with
scale_xxx_manual
. scale_xxx_manual
allows you to provide a values vector that is longer than the actual number of curves, so it's easy to compute the style vector values from the sizes of the Type and Method factors
这篇关于如何在ggplot中合并颜色、线条样式和形状图例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!