How do I differentiate series that have equal values in a plot?

Viewed 81

Sometimes, when I plot multiple series using ggplot, two or more series are identical. The two identical series will not be identical within the plot: each one will have a different color. But one identical series will be plotted over the other. If I have three series, A, B, and C, and C is identical to B, I will see only two lines in the chart. I might try to figure out which of the two chart lines is representing two series by looking at the colors. This may work in simple cases, but with more than three series it is cumbersome and maybe impossible.

One solution to this problem might be doing point charts, that is, using geom_point() and use different shapes for the series. This might work, although awkwardly, for short series. With thousands of points in each series it does not help, as this example shows.

library(tidyverse)

ind <- seq.int(1000)
x <- (1 + runif(1000)/100) %>% cumprod %>% log()
y <- (1 + runif(1000)/200) %>% cumprod %>% log()
z <- y

df <- data.frame(Ind = ind, A = x, B = y, C = z)

dfp <- pivot_longer(df,
                    cols=c("A", "B", "C"),
                    names_to="Series")

p <- ggplot(data=dfp, aes(x=Ind, y = value,
                          col = Series,
                          shape = Series)) +
  geom_point()

p

So here is my question: Is there a way to let users easily see which series have been plotted in the same line when some series are identical?

1 Answers

To deal with overplotting, it will take a combination of parameters, GGPlot2 describes couple of method:

  1. alpha: using alpha you can control the opacity of overlaying plots i.e. the layer which is plotted on top of another, you can make it translucent to show the data of underline layers.
  2. size: you can control the size of overlaying layers, making one bigger while other smaller
  3. linetype or shape: as you highlighted one of the way is to use different shapes and linetypes as well
  4. geom_jitter: You can use geom_jitter instead of geom_point. It adds a random noise to the points and is helpful to deal with overplotting.
  5. Also if applicable, you can try other types of plots as well, as highlighted in comment by @Rui Barradas, facet_wrap can be one way or density plots can be an another method.
  6. If applicable, you can only show the required section of plots i.e. show only the range which the user needs to show by zooming in on the plot or selecting a subset of data. With small data size, the effect of above mentioned aesthetics becomes apparent.

I have tried to create a plot using all the above mentioned points and tried to circumvent the issue of overplotting.

library(tidyverse)
#> Warning: package 'dplyr' was built under R version 4.0.3

ind <- seq.int(1000)
x <- (1 + runif(1000)/100) %>% cumprod %>% log()
y <- (1 + runif(1000)/200) %>% cumprod %>% log()
z <- y

df <- data.frame(Ind = ind, A = x, B = y, C = z)

dfp <- pivot_longer(df,
                    cols=c("A", "B", "C"),
                    names_to="Series")

p <- ggplot() +
  geom_jitter(aes(x=Ind, y = value, color="A"), data = dfp[dfp$Series == "A", ], alpha = 1) +
  geom_jitter(aes(x=Ind, y = value, color="B"), data = dfp[dfp$Series == "B", ], alpha = 1, size=2) +
  geom_jitter(aes(x=Ind, y = value, color="C"), data = dfp[dfp$Series == "C", ], alpha = 0.5, size=0.05) +
  scale_color_manual(name="Series", values=c("A"="green", "B"="steelblue", "C"="orange"))

p

Created on 2021-07-03 by the reprex package (v0.3.0)

Related