为什么我使用ggplot2不能得到两个图例?

4

我正在将不同模型的预测线绘制在一些数据点上。我想要一个图例,指示每个点颜色属于哪个个体,另一个图例指示每条线颜色属于哪个模型。以下是一个可重现的虚假示例:

set.seed(123)
df <- data.frame(Height =rnorm(500, mean=175, sd=15),
                 Weight =rnorm(500, mean=70, sd=20),
                 ID = rep(c("A","B","C","D"), (500/4)))

mod1 <- lmer(Height ~ Weight + (1|ID), df)
mod2 <- lmer(Height ~ poly(Weight,2) + (1|ID), df)

y.mod1 <- predict(mod1, data.frame(Weight=df$Weight),re.form=NA) # Prediction of y according to model 1
y.mod2 <- predict(mod2, data.frame(Weight=df$Weight),re.form=NA) # Prediction of y according to model 2

df <- cbind(df, y.mod1,y.mod2)
df <- as.data.frame(df)

head(df)

    Height   Weight ID   y.mod1   y.mod2
1 166.5929 57.96214  A 175.9819 175.4918
2 171.5473 50.12603  B 176.2844 176.3003
3 198.3806 90.53570  C 174.7241 174.7082
4 176.0576 85.02123  D 174.9371 174.5487
5 176.9393 39.81667  A 176.6825 177.7303
6 200.7260 68.09705  B 175.5905 174.8027

首先,我绘制我的数据点:

Plot_a <- ggplot(df,aes(x=Weight, y=Height,colour=ID)) + 
  geom_point() +
  theme_bw() +
  guides(color=guide_legend(override.aes=list(fill=NA)))

Plot_a

enter image description here

然后,我添加了与预测模型相关的代码行:
Plot_b <- Plot_a + 
  geom_line(data = df, aes(x=Weight, y=y.mod1,color='mod1'),show.legend = T) + 
  geom_line(data = df, aes(x=Weight, y=y.mod2,color='mod2'),show.legend = T) +
  guides(fill = guide_legend(override.aes = list(linetype = 0)),
         color=guide_legend(title=c("Model")))

Plot_b

enter image description here

有人知道为什么我没有得到两个不同的图例,一个标题为Model,另一个为ID吗?

我想要得到这个。

enter image description here

2个回答

6
这类问题通常与数据重塑有关。格式应该是长格式,而数据是宽格式。请参见此帖子,了解如何将数据从长格式转换为宽格式。
绘图层变得更简单了,一个geom_line就足够了,不需要guide来覆盖美学效果。
要自定义模型的图例文本,请创建一个图例向量,在这种情况下使用plotmath进行数学符号表示。颜色也是手动设置的。
library(dplyr)
library(tidyr)
library(ggplot2)

model_labels <- c(expression(X^1), expression(X^2))

df %>%
  pivot_longer(
    cols = c(y.mod1, y.mod2),
    names_to = "Model",
    values_to = "Value"
  ) %>%
  ggplot(aes(Weight, Height)) +
  geom_point(aes(fill = ID), shape = 21) +
  geom_line(aes(y = Value, color = Model)) +
  scale_color_manual(labels = model_labels, 
                     values = c("coral", "coral4")) +
  theme_bw()

enter image description here


@谢谢Rui,我可以问你一个问题吗?如果我想把名称y.mod1y.mod2改为,我应该在开始时更改变量名吗?此外,在我的实际情况中有5行,所以我认为最好的方法是自定义线条的颜色。我用scale_color_manual()来做这个吗?再次感谢您的时间。 - Dekike
@Dekike 是的,应该使用 scale_color_manual 来完成。请参见编辑部分。新颜色只是一个示例。 - Rui Barradas

5
问题在于,在ggplot2中每个美学只能有一个比例尺和一个图例。由于您仅使用了color aes,因此只得到一个图例。如果要为相同的美学获得多个图例,请查看ggnewscales包。否则,必须使用第二个美学。
我偏爱@RuiBarradas提出的方法。但是,为了紧跟您的方法,可以按以下方式实现:
  1. 在对geom_line的调用中,将颜色映射到linetype上。
  2. 设置行的颜色作为参数,即不要在aes内部。
  3. 利用scale_linetype_manual获取两个模型的实线。
  4. 利用guide_legend修复出现在图例中的颜色。
library(ggplot2)
library(lme4)
#> Loading required package: Matrix

set.seed(123)
df <- data.frame(Height =rnorm(500, mean=175, sd=15),
                 Weight =rnorm(500, mean=70, sd=20),
                 ID = rep(c("A","B","C","D"), (500/4)))

mod1 <- lmer(Height ~ Weight + (1|ID), df)
mod2 <- lmer(Height ~ poly(Weight,2) + (1|ID), df)

y.mod1 <- predict(mod1, data.frame(Weight=df$Weight),re.form=NA) # Prediction of y according to model 1
y.mod2 <- predict(mod2, data.frame(Weight=df$Weight),re.form=NA) # Prediction of y according to model 2

df <- cbind(df, y.mod1,y.mod2)
df <- as.data.frame(df)
Plot_a <- ggplot(df) + 
  geom_point(aes(x=Weight, y=Height, colour=ID)) +
  theme_bw() +
  guides(color=guide_legend(override.aes=list(fill=NA)))

line_colors <- scales::hue_pal()(2)
Plot_b <- Plot_a + 
  geom_line(aes(x=Weight, y=y.mod1, linetype = "mod1"), color = line_colors[1]) + 
  geom_line(aes(x=Weight, y=y.mod2, linetype = "mod2"), color = line_colors[2]) + 
  scale_linetype_manual(values = c(mod1 = "solid", mod2 = "solid")) +
  labs(color = "ID", linetype = "Model") +
  guides(linetype = guide_legend(override.aes = list(color = line_colors)))

Plot_b


非常感谢@stefan,我有一个(愚蠢的)疑问。如果我想将行命名为,我该怎么做?我的意思是,如果我在您的代码中更改linetype =“mod1”linetype =“X¹”,那么我必须将mod1 =“solid”更改为X¹ =“solid”,但是这最后一个不被允许。我不能在没有""的情况下使用。我该如何解决这个问题? - Dekike
1
最简单的方法是在 scale_linetype_manual 中使用 labels 参数设置标签,即 labels = c(mod1 = bquote(~X^1), mod2 = bquote(~X^2)) - stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接