如何在R中在不同的图层中生成不同的geom_vline?

31
我正在尝试在数据集的两个不同面板中生成2条不同颜色的geom_vlines。我这样做是为了突出显示两个不同面板的平均值。 以下是数据集:
Pclass  Sex    Age  SibSp   Parch   Fare    Cabin   Embarked    Survived
  3     male    22   1        0     7.25                S          0    
  1     female  38   1        0    71.2833   C85        C          1
  3     female  26   0        0     7.925               S          1    
  1     female  35   1        0    53.1     C123        S          1
  3     male    35   0        0     8.05                S          0    
  1     male    54   0        0    51.8625   E46        S          0

以下是代码:

g<-ggplot(data = train3, aes(x = Age, y = Survived, colour = factor(Pclass)))
g<-g+facet_wrap(~Sex)
g<-g+geom_point(size = 4, alpha = 0.2)+ggtitle("Survival by Gender")+theme(plot.title = element_text(hjust = 0.5))
g<-g+geom_vline(data = subset(train3,Sex=="female"), xintercept = mean(train3[which(train3$Sex=="female"),3]), colour = "pink", size = 1)
g<-g+geom_vline(data = subset(train3,Sex=="male"), xintercept = mean(train3[which(train3$Sex=="male"),3]), colour = "blue", size = 1)
g

这是输出结果:

在此输入图像描述

我想在每个面板中只生成一条竖线:女性面板中为粉色,男性面板中为蓝色。

这里给出的建议 不起作用, 出现以下错误:

Error in .(Sex == "female") : could not find function "."

请提供可重现的示例。 - Adam Quek
3个回答

43

以下是如何为不同的鸢尾花物种使用不同的geom_vline

ggplot(iris, aes(Sepal.Length, Petal.Length)) + facet_wrap(~Species, scales="free") + geom_point() + 
  geom_vline(data=filter(iris, Species=="setosa"), aes(xintercept=5), colour="pink") + 
  geom_vline(data=filter(iris, Species=="versicolor"), aes(xintercept=6), colour="blue") + 
  geom_hline(data=filter(iris, Species=="virginica"), aes(yintercept=6), colour="green") 

输入图像描述


传奇!!显然data调用中的子集函数没有起作用。很高兴发现过滤器起了作用。感谢您的快速帮助。非常感激。 - Scott85044
1
我认为错误是由于aes中没有声明xintercept引起的吗? - Adam Quek
比较 geom_vline(data=subset(iris, Species=="setosa"), aes(xintercept=5), colour="pink")geom_vline(data=subset(iris, Species=="setosa"), xintercept=5, colour="pink") - Adam Quek
6
针对三个方面,这种方法运作良好,但是否有办法在大量方面上高效地实现呢? - S. Robinson
1
这看起来更容易适用于多个方面 https://dev59.com/F2gu5IYBdhLWcg3w9ryX - Mark Neal

24

你可以创建一个数据框,其中一列是代表拟合直线的截距值,另一列是性别。这样,在使用facet_wrap时,它们就会被分开。
类似于这样:

dataInt <- train3 %>%
  group_by(Sex) %>%
  summarize(Int = mean(Age))

然后您可以在您的脚本中使用它:

g<-ggplot(data = train3, aes(x = Age, y = Survived, colour = factor(Pclass))) + 
  facet_wrap(~Sex) +
  geom_vline(data=dataInt, aes(xintercept=Int))

没有你的数据,我无法测试。

[编辑:使用可重现示例] 如果我使用Adam Quek的相同数据来创建一个可重现的示例,代码将自动执行如下:

library(tidyverse)

dataLine <- iris %>%
  group_by(Species) %>%
  summarize(mean_x = mean(Sepal.Length))

ggplot(iris) +
  aes(x = Sepal.Length, y = Petal.Length) +
  facet_wrap(facets = vars(Species)) + 
  geom_point() + 
  geom_vline(data  = dataLine, aes(xintercept = mean_x, colour = Species))

ggplot2: line for mean for each facet


不要使用函数summarize(Int = mean(Age))创建一个名为dataInt的新数据集,因为这对我来说行不通。相反,应该使用mutate。 - George
这个答案很棒,因为它允许根据数据自动计算的值来灵活调整行。 - Kirk Geier
1
如果您有兴趣调整线条的属性,请使用以下语法:
  • geom_vline(data = dataLine, aes(xintercept = mean_x), linetype="dashed", size = 1.5, colour = "green")
- Kirk Geier

2

在 @Sébastien Rochette 的回答基础上进行改进; 不要使用函数 summarize(Int = mean(Age)) 创建一个名为 dataInt 的新数据框,因为我在每个面板绘图中都有多个水平,所以这种方法对我不起作用。相反,使用 mutate。

train3 <- train3 %>%
  group_by(Sex) %>%
  mutate(Int = mean(Age))

然后您可以在train3数据帧中使用

g<-ggplot(data = train3, aes(x = Age, y = Survived, colour = factor(Pclass))) + 
  facet_wrap(~Sex) +
  geom_vline(data=train3, xintercept=Int)

这个方法是可行的,但我担心它可能会为所有值创建一个geom_vline,因为每个平均值将在数据框架内每个因子的每个水平上重复出现。


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