Here’s some data with x and y values, along with two grouping variables level1 and level2. I’d like to plot the grouping variables with colour and linetype aesthetics, like this:
library(ggplot2)
library(dplyr)
set.seed(100)
dat <- data.frame(
x = rep(2010:2014, each = 6),
level1 = rep(letters[1:3], times = 10),
level2 = rep(rep(c("y", "z"), each = 3), times = 5),
y = rnorm(30)
)
dat %>%
ggplot(aes(x = x, y = y, colour = level1, linetype = level2)) +
geom_line()
This plot is actually correct. The problem is when I change the x-axis to a factor (or character):
dat %>%
mutate(x = factor(x)) %>%
ggplot(aes(x = x, y = y, colour = level1, linetype = level2)) +
geom_line()
geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
That seems fair enough, I never actually specified the group aesthetic, it just seemed to work out of the box when x was numeric. My first thought was to specify group = level1, but that leads to
Error: geom_path: If you are using dotted or dashed lines, colour, size and linetype must be constant over the line
Which also seems reasonable, because there are actually six lines, and they’re defined by the combination of level1 and level2, not just level1. But I’m not sure it’s possible to specify a multi-level line grouping, e.g.,
dat %>%
mutate(x = factor(x)) %>%
ggplot(aes(x = x, y = y, colour = level1, linetype = level2)) +
geom_line(aes(group = c(level1, level2)))
Error: Aesthetics must be either length 1 or the same as the data (30): group
The desired output is a reproduction of the first plot, but with the x-variable as a factor rather than numeric. Any insight into why the plot seems to work when x is numeric would be interesting as well. Thanks.
>Solution :
You had generally the right idea trying to use two grouping variables. To do this you need to use the interaction between level1 and level2 in the group argument.
library(ggplot2)
library(dplyr)
dat %>%
mutate(x = factor(x)) %>%
ggplot(aes(x = x, y = y, colour = level1, linetype = level2, group = interaction(level1, level2))) +
geom_line()
