'How to produce different geom_vline in different facets in R?

I am trying to produce 2 different geom_vlines with different colours in 2 different facets of a dataset. I am doing this to highlight means of 2 different facets.

Here's the dataset:

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

Here's the code:

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

Here's the output

enter image description here

I actually want to produce only 1 vline in each facet: pink in female and blue in male.

The suggestion give here is not working either . Error shown being:

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


Solution 1:[1]

Here's how you can put in different geom_vline for different iris species:

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") 

enter image description here

Solution 2:[2]

You can create a data.frame with one column being intercept values to be used for lines and a second column with Sex. So that when using facet_wrap, they are separated.
Something like:

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

Then you can use it in your script:

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

Without your data, I cannot test this.

[EDIT: With a reprex] If I use the same data as Adam Quek for a reproducible example, the code would be automated as follows:

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

Solution 3:[3]

Building on @Sébastien Rochette's answer above; Rather than creating a new data frame dataInt with the function summarize(Int = mean(Age)), which didn't work for me as I had multiple levels within each facet plot, use mutate instead.

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

And then you can use train3 data-frame in

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

This works but I fear it may have created a geom_vline for all values, because each mean will be repeated within each level of each factor within the dataframe.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Adam Quek
Solution 2
Solution 3 George