Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2: differentiate lines by both color and linetype

Tags:

r

ggplot2

So when I have to plot a lot of lines I can differentiate them by color or linetype

library(ggplot2)
pd = cbind.data.frame(x = rep(c(1,2), each = 4), 
              y = rep(1:4, times=2), 
              type = rep(c("A", "B", "C", "D"), times=2))
ggplot(pd, aes(x=x, y=y, col=type)) + geom_line() + theme_bw()
ggplot(pd, aes(x=x, y=y, lty=type)) + geom_line() + theme_bw()

giving:

enter image description here enter image description here

but I want both and I want colors and linetypes to be chosen automatically (i.e. I don't want to specify manually color and linetype for each type as in this question: ggplot2 manually specifying color & linetype - duplicate legend).

Here is an example of what my desired output could look like (plus an automatically generated legend):

enter image description here

ideal would be a command like

ggplot(pd, aes(x=x, y=y, style=type)) + geom_line() + theme_bw()

but I guess there will need to be a workaround.

P.S: the motivation of this is that 20+ lines can be hard to differentiate by color or linetype alone, this is why I'm looking for a combination of both. So the dashed red line is different from the solid red line and both of those yet different from the solid blue line. And I don't want to specify and choose colors and linetypes myself each time I feed my data to ggplot.

like image 713
mts Avatar asked Feb 02 '26 17:02

mts


1 Answers

I know you wanted to avoid manual specification, but it doesn't have to be anywhere near as daunting as the example you linked to. Example below for 20 lines (color_lty_cross can accommodate up to 60):

library(ggplot2)

pd = cbind.data.frame(x = rep(c(1,2), each = 20), 
                      y = rep(1:20, times=2), 
                      type = rep(LETTERS[1:20], times=2))

# this function regenerates ggplot2 default colors
gg_color_hue <- function(n) {
  hues = seq(15, 375, length = n + 1)
  hcl(h = hues, l = 65, c = 100)[1:n]
}

color_lty_cross = expand.grid(
  ltypes = 1:6,
  colors = gg_color_hue(10)
  ,stringsAsFactors = F)


ggplot(pd, aes(x=x, y=y, col=type, lty = type)) + 
  geom_line() + 
  scale_color_manual(values = color_lty_cross$colors[1:20]) +
  scale_linetype_manual(values = color_lty_cross$ltypes[1:20]) +
  theme_bw()

You could quickly map to type with a merge You could use use simpler colors then gg_color_hue which maps ggplot2 defaults.

  • Credit for gg_color_hue to Emulate ggplot2 default color palette.

enter image description here

like image 105
bmayer Avatar answered Feb 05 '26 07:02

bmayer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!