2

What I am trying to do is to tell ggplot to geom_line a column of a tibble that is quoted with ``.

For instance, if I write literally the "name" of the column it works:

this is the generated tibble:

Q <- as_tibble(data.frame(series = rep(c("diax","diay"),3),
                          value = c(3.25,3.30,3.31,3.36,3.38,3.42),
                          year = c(2018,2018,2019,2019,2020,2020))) %>%
  select(year, series, value) %>% spread(key = "series", value = "value") %>%
  rename(`2018-01-01` = diax, `2017-01-01` = diay)

And this is the ggplot command:

ggplot(Q, aes(x = year)) + 
  geom_line(aes(y = `2018-01-01`), col = "red", size = 2, linetype = "dotdash") +
  geom_line(aes(y = `2017-01-01`), col = "orange", size = 2, linetype = "dashed")

The code above works just fine.

But if I have a vector of strings with the name of the columns, I simply cannot replicate the previous result calling the vector.

That is, suppose I have a vector like this:

nomes <- c("2018-01-01","2017-01-01")

and then I would like ggplot something like this:

ggplot(Q, aes(x = year)) + 
  geom_line(aes(y = nomes[1]), col = "red", size = 2, linetype = "dotdash") +
  geom_line(aes(y = nomes[2]), col = "orange", size = 2, linetype = "dashed")

I know that this wouldn´t work, but as a beginner that I am, I would guess that the lines below would work just fine, but they don´t

ggplot(Q, aes(x = year)) + 
  geom_line(aes(y = !!quo(nomes[1])), col = "red", size = 2, linetype = "dotdash") +
  geom_line(aes(y = !!quo(nomes[2])), col = "orange", size = 2, linetype = "dashed")

I realized that quo(nomes[1]) does not deliver the name inside the position of the vector, and I could not get what I wanted trying some alternatives I though about.

motabe
  • 101
  • 1
  • 6
  • Is there a reason why you want to do this from wide shaped data? You can keep it as it was before `spread` and then map color and linetype onto `series` in your `aes` call. It would be simpler and scalable – camille May 07 '18 at 00:50
  • yes, I need to ggplot by column, specifying each of the easthetics independently, otherwise, I would not get the exactly aspect in my charts. To be more precise, each line should come on to p of the precedent one, with labels included, so the most recent results are the oned that are crystal clear on top. tks a lot for the help! – motabe May 07 '18 at 10:35
  • Cool, I don't want to hound you about it, but I got the same plot as in the answer below, while keeping the data in its original long format. I can post if you like – camille May 07 '18 at 12:36
  • Hi @camille, yes please! – motabe May 07 '18 at 18:33

2 Answers2

2

You can as.name:

nomes <- c("2018-01-01","2017-01-01");
ggplot(Q, aes(x = year)) +
    geom_line(aes(y = !!as.name(nomes[1])), col = "red", size = 2, linetype = "dotdash") +
    geom_line(aes(y = !!as.name(nomes[2])), col = "orange", size = 2, linetype = "dashed");

enter image description here

Or use rlang::sym:

ggplot(Q, aes(x = year)) +
    geom_line(aes(y = !!rlang::sym(nomes[1])), col = "red", size = 2, linetype = "dotdash") +
    geom_line(aes(y = !!rlang::sym(nomes[2])), col = "orange", size = 2, linetype = "dashed");

Explanation: We convert a string into a symbol with as.name or rlang::sym, and then evaluate the symbol in the current surrounding context with !!.

Maurits Evers
  • 49,617
  • 4
  • 47
  • 68
  • The `!!` should introduce problems if you use `as.name()`. `as.name(nomes[1])` seems like it should work by itself, no? – Marcus Campbell May 06 '18 at 23:02
  • @MarcusCampbell You still need the `!!` to unquote (i.e. evaluate) the symbols. – Maurits Evers May 07 '18 at 00:53
  • Are you sure? I'm only asking because when I run your code, `!!as.name(nomes[1])` throws an error, but `as.name(nomes[1])` gives the desired result. I believe this is because the output of `as.name()` is wrapped in backticks and not quotes, so the use of `!!` is unnecessary. – Marcus Campbell May 07 '18 at 01:22
  • @MarcusCampbell Yes, very sure. In fact, I'm getting an error when I run as `as.name(nomes[1])`. That's odd. I'm using `dplyr_0.7.4` and `rlang_0.2.0.9000`. – Maurits Evers May 07 '18 at 02:20
  • @MarcusCampbell Can you check your `rlang`/`dplyr` versions? If this is a version issue, I will edit my post to include a note. – Maurits Evers May 07 '18 at 02:23
  • Thank you for your patience with me. I am using exactly the same package versions. The issue appears to be that the first `!` is being interpreted as a negation. But I've copied and pasted the exact code in your post (and re-tried this multiple times after clearing my workspace). Very bizarre...probably the strangest thing to me is that using `as.name()` without the `!!` appears to work just fine!! – Marcus Campbell May 07 '18 at 03:31
  • @MarcusCampbell Yes, that's very bizarre indeed. I've re-run my code multiple times, and I've got no issues. I'd say that you definitely *should* be needing the `!!`, which is consistent with e.g. [this post](https://stackoverflow.com/questions/44121728/programming-with-dplyr-using-string-as-input). Hadley also suggests `as.name` as an alternative to `rlang::sym` [here](https://github.com/r-lib/rlang/issues/116#issuecomment-298985481). – Maurits Evers May 07 '18 at 03:38
  • @MarcusCampbell Do you still get an error when wrapping `!!` in backticks and placing the expression in brackets? E.g. `\`!!\`(as.name(nomes[1]))`? – Maurits Evers May 07 '18 at 04:22
  • Yes, I tried exactly that. I got the error ` `!!` can only be used within a quasiquoted argument ``. I use `!!` in some of my other scripts and it has always worked predictably fine. I suspect I am doing something...wrong...here, but I'd rather not clog up the comments on this answer. I greatly appreciate your help. I'll ask my colleagues tomorrow morning to run the same code and see what we all get. Perhaps I'll end up having to ask my first question on SO! – Marcus Campbell May 07 '18 at 04:52
  • No worries @MarcusCampbell. – Maurits Evers May 07 '18 at 05:55
  • @MarcusCampbell and Maurits Evers I´ve used the version of the answer in the morning as.name and it worked perfeclty. Now, a couple of hors late, it simply doesn´t work, I've got the exactly same error you were reporting... – motabe May 07 '18 at 17:25
  • Maurits Evers and @MarcusCampbell, what versions of R are you using? – motabe May 07 '18 at 19:19
  • @motabe I'm running R 3.4.0. Did the solution with `!!rlang::sym(...)` work? – Maurits Evers May 07 '18 at 21:18
  • Nope, I really don´t understand it. I got the following errors: Error in !as.name(nomes[1]) : invalid argument type and Error in !rlang::sym(nomes[1]) : invalid argument type – motabe May 11 '18 at 20:39
  • What it is really intriguing me, is the fact that it worked at first. I had some problems with rlang installation. i´ve re-installed and now it is working but not with the code above. I don´t know if this is some sort of deparsing, perhaps witth the base R.. – motabe May 11 '18 at 21:30
  • @motabe If you can reproduce the error(s) with a minimal example like in this post, perhaps you should post an issue on the `rlang` or `dplyr` github project sites. I don't understand what's going on. Just to be clear: I assume you're starting from a fresh R terminal, no saved workspace, load the necessary `tidyverse` libraries, and copy&paste above code into the terminal? – Maurits Evers May 12 '18 at 01:27
  • Yes, starting from a fresh terminal and required libraries loaded... Thanks a lot, I reading advance R in order to better understand quasicotation, at least to leave complete ignorance behind... But I am going to do what you´ve suggested. Thank you so much for the help. For the record, I am running rlang 0.2.0 and R 3.4.4. Cheers – motabe May 12 '18 at 14:24
0

As far as I can tell, this is the same as what you're looking for, but without the naming hassle. You can keep your data in long format, and map color and linetype onto the series column. I used fct_recode from forcats (ships as part of tidyverse) to change the factor levels of series, but you can change levels in base R as well.

Alternatively, you could keep the series levels as they are (diax, diay), and just change the labels as they appear in the legend in scale_color_manual and scale_linetype_manual.

library(tidyverse)

df <- as_tibble(data.frame(series = rep(c("diax","diay"),3),
                 value = c(3.25,3.30,3.31,3.36,3.38,3.42),
                 year = c(2018,2018,2019,2019,2020,2020))) %>%
    mutate(series = fct_recode(series, "2018-01-01" = "diax", "2017-01-01" = "diay"))

ggplot(df, aes(x = year, y = value, color = series, linetype = series)) +
    geom_line(size = 2) +
    scale_color_manual(values = c("2018-01-01" = "red", "2017-01-01" = "orange")) +
    scale_linetype_manual(values = c("2018-01-01" = "dotdash", "2017-01-01" = "dashed"))

Created on 2018-05-07 by the reprex package (v0.2.0).

camille
  • 16,432
  • 18
  • 38
  • 60
  • tks! But, as I mentioned, the problem I am facing is to tackle exactly those `names` on columns. The way I´ve written here is forcing an not natural way of doing things, kind of unnecessarily complicating things, I beg your pardon for that, but it would be simpler to explain exactly what my difficult is. Cheers! – motabe May 07 '18 at 19:10