1

I learnt how to put vertical and horizontal lines on a facetted plot from here. Now I wanted to modify the code so that I could pass the xintercept and yintercept using a variable, however, I don't think I am using aes or aes_ correctly.

First, let us replicate the original example (with slightly different intercepts:

# set up data
library(ggplot2)
tmp_intercepts <- data.frame(x = c(5, 3, 1))
iris$species_num <- as.numeric(iris$Species)
p <- 
    ggplot(iris, aes(Sepal.Length, Petal.Length)) + facet_wrap(~Species, scales="free") + geom_point()

## original plot works fine

for (i in 1:3) {


    if (i == 1) {
        p_orig <- 
            p +
            geom_vline(data=filter(iris, species_num == i), aes(xintercept=5), colour="pink")
    } else if (i == 2) {
        p_orig <- 
            p_orig +
            geom_vline(data=filter(iris, species_num == i), aes(xintercept=3), colour="blue")
    } else {
        p_orig <- 
            p_orig +
            geom_hline(data=filter(iris, species_num == i), aes(yintercept=1), colour="green") 


    }

}

I will now make two plots, one using a loop with aes, and the other using aes_. Both fail to reproduce the first plot (Look at the location of the vertical lines).

## but once you try to pass in a variable it fails

for (i in 1:3) {


    if (i == 1) {
        p_loop <- 
            p +
            geom_vline(data=filter(iris, species_num == i), aes(xintercept=tmp_intercepts$x[i]), colour="pink")
    } else if (i == 2) {
        p_loop <- 
            p_loop +
            geom_vline(data=filter(iris, species_num == i), aes(xintercept=tmp_intercepts$x[i]), colour="blue")
    } else {
        p_loop <- 
            p_loop +
            geom_hline(data=filter(iris, species_num == i), aes(yintercept=tmp_intercepts$x[i]), colour="green") 


    }

}



## if you do it one by one it is not fine either!

tmp_x  <- 5
p_obo <- 
    p +
    geom_vline(data=filter(iris, species_num == 1), aes_(xintercept=quote(tmp_x)), colour="pink")

tmp_x <- 3
p_obo <- 
    p_obo +
    geom_vline(data=filter(iris, species_num == 2), aes_(xintercept=quote(tmp_x)), colour="blue")

tmp_x <- 1
p_obo <- 
    p_obo +
    geom_hline(data=filter(iris, species_num == 3), aes_(yintercept=quote(tmp_x)), colour="green") 

Plotting so that the original is at the top via plot(gridExtra::arrangeGrob(p_orig, p_loop, p_obo, ncol = 1)):

enter image description here

I think I am using aes incorrectly.

Alex
  • 15,186
  • 15
  • 73
  • 127
  • wow, why the downvotes? – Alex Apr 18 '18 at 11:36
  • 1
    I didn't down-vote but perhaps it has to do with your question record and your surprisingly low acceptance rate, despite having received great and multiple answers. In my opinion, your question is well presented with extensive sample code, as seems to be the case for most of your questions. I'd recommend accepting answers to acknowledge a similar amount of effort put in by SO respondents for answering your questions. – Maurits Evers Apr 18 '18 at 12:31
  • Thank you for your comment @MauritsEvers. I am not sure that is entirely a valid reason to downvote but I accept that people can do whatever they want with the buttons provided to them. The following is not related to this question, but based on your prompting, I have had a look at my most recent 30 questions. 10 have accepted answers, 9 are unanswered, and 11 had answers not accepted by me. Breaking the latter down, I just accepted an additional two, classed three as not satisfactory, two I did not test, two I am unsure which is the best answer, and two I self answered... – Alex Apr 18 '18 at 23:39
  • ... if it is any comfort to you, I upvote answers whenever they seem like they are helpful to the R community in general, and generally also make comments on these answers. However, I don't like accepting answers unless I am very sure that the answer is right. – Alex Apr 18 '18 at 23:42
  • Take the answer by @PoGibas for example. It is a good approach to produce an equivalent plot, which I have upvoted. However, it does not answer my question about `aes` and why it doesn't work with `geom_vline`. – Alex Apr 18 '18 at 23:42
  • *" if it is any comfort to you"* Let me clarify that I have no stake in this: So far I've not been involved in voting for or answering any of your questions. So no need to comfort. Having read your clarification I disagree with your view on accepting answers; mainly because I don't think it does what you claim it does: help the R community. Obviously it is your right to do so, as it is the right of the R community to down-vote. I was only offering an explanation for the down-votes. Personally I think they are a bit harsh, and not an accurate reflection of your question's quality. – Maurits Evers Apr 19 '18 at 01:19

2 Answers2

1

When you think about it - intercepts are just very narrow rectangles. If you don't need fancy linetype then you can use them (this solution removes looping part):

# Create intercept data    
dataInt <- data.frame(Position = c(5, 3, 1),
                      Species  = levels(iris$Species),
                      Type     = c("x", "x", "y"))
#  Position    Species Type
#         5     setosa    x
#         3 versicolor    x
#         1  virginica    y

library(ggplot2)
ggplot() + 
    geom_point(data = iris, 
               aes(Sepal.Length, Petal.Length)) +
    geom_rect(data = dataInt,
              aes(xmin = ifelse(Type == "x", Position, -Inf), 
                  xmax = ifelse(Type == "x", Position, Inf), 
                  ymin = ifelse(Type == "x", -Inf, Position), 
                  ymax = ifelse(Type == "x", Inf, Position), 
                  color = Species),
              size = 0.5) +
    facet_wrap(~ Species, scales = "free") +
    theme(legend.position = "none")

enter image description here

pogibas
  • 27,303
  • 19
  • 84
  • 117
0

My issue is that I did not properly understand the ggplot2 help page on aes_. Specifically, I was following the instruction aes_ and aes_string require you to explicitly quote the inputs either with "" for aes_string(), or with quote or ~ for aes_().

Now, the reason why calling the variable in a loop or otherwise does not work is because aes() does not perform evaluation of its arguments. Indeed, aes_ is the way to force a variable to be evaluated. However, if the variable is in the global environment and not inside the data frame passed to ggplot, it seems that you do not have to 'quote' its name.

The following produces the same plot as the first one:

tmp_x  <- 5
p_f <- 
    p +
    geom_vline(data=filter(iris, species_num == 1), aes_(xintercept=tmp_x), colour="pink")

tmp_x <- 3
p_f <- 
    p_f +
    geom_vline(data=filter(iris, species_num == 2), aes_(xintercept=tmp_x), colour="blue")

tmp_x <- 1
p_f <- 
    p_f +
    geom_hline(data=filter(iris, species_num == 3), aes_(yintercept=tmp_x), colour="green") 
plot(p_f)

enter image description here

Alex
  • 15,186
  • 15
  • 73
  • 127