ggplot2:如何让符号在两个不同的散点图中保持相同?

Tho*_*mas 4 r ggplot2

这个问题一直让我抓狂.我正在尝试使用两个不同的数据集制作散点图.我的数据框是

structure(list(x1 = c(5L, 3L, 4L, 5L, 4L, 8L, 5L, 6L, 3L, 4L, 
5L, 6L, 8L, 4L), y1 = c(7L, 5L, 6L, 4L, 1L, 5L, 6L, 9L, 8L, 4L, 
5L, 6L, 7L, 8L), class1 = structure(c(1L, 2L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L), .Label = c("A", "B"), class = "factor"), 
x2 = c(4L, 8L, 7L, 5L, 6L, 2L, 5L, 4L, 5L, NA, NA, NA, NA, 
NA), y2 = c(7L, 5L, 1L, 4L, 5L, 8L, 4L, 5L, 8L, NA, NA, NA, 
NA, NA), class2 = structure(c(3L, 2L, 2L, 2L, 3L, 2L, 2L, 
3L, 3L, 1L, 1L, 1L, 1L, 1L), .Label = c("", "A", "B"), class = "factor")), .Names = c("x1", 
"y1", "class1", "x2", "y2", "class2"), class = "data.frame", row.names = c(NA, 
-14L))
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

x1  y1  class1  x2  y2  class2
5   7   A       4   7   B
3   5   B       8   5   A
4   6   A       7   1   A
5   4   A       5   4   A
4   1   B       6   5   B
8   5   B       2   8   A
5   6   B       5   4   A
6   9   B       4   5   B
3   8   B       5   8   B
4   4   A
5   5   A
6   6   A
8   7   A
4   8   A
Run Code Online (Sandbox Code Playgroud)

我想绘制两个散点图:

  1. x1 VS y1
  2. x2 VS y2

在每个散点图中,我希望符号形状由类class1class2.由于类是A或者B,我希望符号形状在两个图中保持相同.

我使用以下代码尝试执行此操作:

library(ggplot2)
theme_set(theme_bw()) # omit grey background

qplot(x1, y1, data=df, shape=I(21), fill=I("gray"), size = I(4),alpha = I(0))+
  stat_smooth(method="lm", se=FALSE, colour="black", size=1) + geom_point(shape=factor(class1),        size=I(4))

qplot(x2, y2, data=df, shape=I(21), fill=I("gray"), size = I(4),alpha = I(0))+
  stat_smooth(method="lm", se=FALSE, colour="black", size=1) + geom_point(shape=factor(class2),     size=I(4))
Run Code Online (Sandbox Code Playgroud)

如果我的长度x1/y1和它x2/y2是相同的,它工作正常- 在这种情况下,符号在两个图中保持相同.但是,如果数据集的长度不同(如上面的数据框示例中所示),则在第二个图中引入第三个符号.

有谁知道我怎么可以得到相同的符号A,并B在这两个地块?

编辑:如果我尝试下面由Didzis Elferts建议的方法

ggplot(df,aes(x1,y1,shape=class1))+geom_point(size=4)+
scale_shape_manual(breaks=c("A","B"),values=c(15,16))

ggplot(df,aes(x2,y2,shape=class2))+geom_point(size=4)+
scale_shape_manual(breaks=c("A","B"),values=c(15,16))
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

Error: Insufficient values in manual scale. 3 needed but only 2 provided.
Run Code Online (Sandbox Code Playgroud)

编辑2:Didzis Elferts推荐以下解决方案

df$class2<-factor(df$class2,levels=c("A","B"))
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用每个散点图添加回归线时

ggplot(df,aes(x1,y1,shape=class1))+geom_point(size=4)+ scale_shape_manual(breaks=c("A","B"),values=c(15,16))+ stat_smooth(method="lm", se=FALSE, colour="black", size=1)

qplot(x2, y2, data=df, shape=class1)+ stat_smooth(method="lm", se=FALSE, colour="black", size=1) + geom_point(size=4)+ scale_shape_manual(breaks=c("A","B"),values=c(15,16))
Run Code Online (Sandbox Code Playgroud)

ggplot2为每个类添加一个单独的回归线.相反,我只需要基于来自两个类的数据的单个回归线(即使它们具有不同的符号).

Did*_*rts 5

问题是,在您的数据中,class2空单元格是因子级别之一.

str(df$class2)
 Factor w/ 3 levels "","A","B": 3 2 2 2 3 2 2 3 3 1 ...
Run Code Online (Sandbox Code Playgroud)

您可以NA通过设置新的因子级别来更改此空单元格.

df$class2<-factor(df$class2,levels=c("A","B"))
Run Code Online (Sandbox Code Playgroud)

确保两个图具有相同图例和符号的一种方法是使用scale_shape_manual()然后设置breaks=values=(形状符号)您需要的方法.

ggplot(df,aes(x1,y1,shape=class1))+geom_point(size=4)+
    scale_shape_manual(breaks=c("A","B"),values=c(15,16))

ggplot(df,aes(x2,y2,shape=class2))+geom_point(size=4)+
    scale_shape_manual(breaks=c("A","B"),values=c(15,16))
Run Code Online (Sandbox Code Playgroud)

更新 - 一条回归线

为了得到只有一个回归线shape=应该直接内放置aes()geom_point().

ggplot(df,aes(x2,y2))+geom_point(size=4,aes(shape=class2))+
           scale_shape_manual(breaks=c("A","B"),values=c(15,16))+
           stat_smooth(method="lm", se=FALSE, colour="black", size=1)
Run Code Online (Sandbox Code Playgroud)