2

I am trying to create a plot where the color gradient changes by both the x and y axis. More specifically I am trying set up the gradients so that the hue range changes along the x axis and the value changes along the y axis.

For an example I am working with a sine curve with some noise along -pi to pi.

set.seed(5678)
x <- seq(-1*pi, 1*pi, 0.01)
y <- sin(x) + rnorm(length(y))
df <- cbind.data.frame(x, y)
ggplot(df, aes(x=x, y=y)) + geom_line()

Now I want to colorize the line so that the hue progresses from red-orange to orange-yellow to yellow-green, etc. along the x axis and then will take on different values in that range depending on its y value. So at x=-pi, y=2 might be red and y=-2 might be yellow while at x=0, y=2 might be green and y=-2 might be blue.

Has anyone tried to create a graph like this?

Nick Kennedy
  • 12,510
  • 2
  • 30
  • 52
Ellis Valentiner
  • 2,136
  • 3
  • 25
  • 36
  • Not exactly what you are looking for, but you could try to map `color` to an interaction of x and y ; `df$xy <- x + y ; ggplot(df, aes(x=x, y=y,color=xy)) + geom_line() + scale_color_gradientn(colours=(c("red","orange","yellow","green")))` – scoa Jul 29 '15 at 17:04
  • And similarly with `colorRampPalette`, `cols <- colorRampPalette(c("red", "orange", "yellow", "green"))(length(x)); ggplot(df, aes(x=x, y=y)) + geom_line(color=cols) + theme_bw()` – Rorschach Jul 29 '15 at 17:24
  • @nongkrong but then the colour varies only along the x axis, whereas the OP wants it to vary along both axes – scoa Jul 29 '15 at 17:26
  • @scoa oh ok, does the interaction not work then? – Rorschach Jul 29 '15 at 17:32
  • @nongkrong This is not exactly what they asked for : with the interaction, the color of a data point x=1 y=2 would be the same as that of x=2 y=1. – scoa Jul 29 '15 at 17:44
  • I would probably look at the color gradient line solution in pkg:plotrix.... not ggplot though. – IRTFM Jul 29 '15 at 17:45
  • So far the best luck I have had is to rescale x and y to be [0,1] and then use their interaction. This isn't quite right, especially since it has non-constant variance. – Ellis Valentiner Jul 29 '15 at 18:09

1 Answers1

3

Here's an option for doing it using a hue calculated from x and y:

df$hue <- pmax(pmin((df$x + pi)/pi/3 + (2 - df$y) / 12, 1), 0)
ggplot(df, aes(x=x, y=y, group = 1, colour = hsv(hue, 1, 1))) + geom_path() +
  scale_colour_identity()

Note because the lines are quite long vertically so the effect isn't fully seen. Here's a version using approx to interpolate:

adf <- as.data.frame(approx(df, xout = seq(-pi, max(df$x), 0.001)))
adf$hue <- pmax(pmin((adf$x + pi)/pi/3 + (2 - adf$y) / 12, 1), 0)
ggplot(adf, aes(x=x, y=y, group = 1, colour = hsv(hue, 1, 1))) + geom_path() +
  scale_colour_identity()

hue plot

In both cases, it's the hue that's dependent on both x and y, with value held constant. That fits your proposed example, if not your original description. Clearly it could be tailored to vary hue and value separately. It's also worth noting that there needs to be a group set. Otherwise ggplot2 tries to join together all the points of the same colour.

Nick Kennedy
  • 12,510
  • 2
  • 30
  • 52