Search code examples
rif-statementggplot2aes

ggplot - Using ifelse inside aes with geom_line gives unlogic result


I am trying to create a chart with two data dependent line formats: the "x opp"-data (high values) with a solid line, and the "x ned"-data (low values) with a longdashed line.

Using this code I get the opposite line format, and to taunt me R even labels the legend opposite

library(ggplot2)
df <- data.frame(
    grp_val=c("x opp", "x opp", "x opp", "x ned", "x ned", "x ned"),
    x_val=c(1, 2, 3, 1, 2, 3),
    y_val=c(14, 16, 15, 5, 7, 6)
)
ggplot(df, aes(x_val, y_val)) +
geom_line(aes(group=grp_val, linetype = ifelse(grepl("opp", grp_val), "solid", "longdash")))

enter image description here I'm guessing the aes is unhappy with an ifelse inside it. But why not throw an error, instead of plotting the opposite? Please give me a hint, cause I'm old and dumb...


Solution

  • When you map on aesthetics inside aes() the values are treated as different categories not as linetypes, i.e. ggplot2 interprets "solid" and "longdash" as two categories like "A" and "B" and assigns the default linetypes. This is quite similar to the result you get when you use e.g. color="blue" inside aes() which instead of a blue line will give you a reddish color picked from the default color palette.

    Instead, if you are mapping literal linetypes (or colours or ...) to aesthetics, you need to use scale_xxx_identity. This way ggplot2 knows that it should interpret the category names as linetype names.

    library(ggplot2)
    
    ggplot(df, aes(x_val, y_val)) +
      geom_line(aes(
        group = grp_val,
        linetype = ifelse(grepl("opp", grp_val), "solid", "longdash")
      )) +
      scale_linetype_identity(guide = "legend")