3

Data:

df1 <- structure(list(Index = 1:11, Duration = structure(c(1487577655, 
1487577670, 1487577675, 1487577680, 1487577685, 1487577680, 1487577700, 
1487577705, 1487577695, 1487577700, 1487577680), class = c("POSIXct", 
"POSIXt"), tzone = "")), .Names = c("Index", "Duration"), class = "data.frame", row.names = 3:13)

Now I construct the graph as follows:

g1 <- ggplot(df1, aes(x = Index, y = Duration, color = Duration))+
geom_point()+
geom_line()+
scale_y_datetime(labels = date_format("%M:%S"))

As it is now, the color scale is set to the default "Black" to "Blue" gradient.

The problem is, I get an error trying to assign a custom gradient to the data.

For a non-POSIXct object:

scale_color_gradient("Duration", low = "#D80427", high = "#07a0ff", space = "Lab")

works, but I get the following error with the POSIXct object df1$Duration as the explanatory variable:

Error in Ops.POSIXt((x - from[1]), diff(from)) : '/' not defined for "POSIXt" objects

Is there a different gradient function I need to use when graphing a POSIXct object?

Henrik
  • 65,555
  • 14
  • 143
  • 159
Mako212
  • 6,787
  • 1
  • 18
  • 37

2 Answers2

4

You may use trans = time_trans():

library(ggplot2)
library(scales)
g1 +
  scale_color_gradient("Duration", low = "#D80427", high = "#07a0ff",
                       trans = time_trans())

enter image description here

If you wish another format of the labels in the legend, add e.g. labels = format(pretty(df1$Duration), "%M:%S").

Henrik
  • 65,555
  • 14
  • 143
  • 159
1

We can convert date to number for colour:

library(ggplot2)
library(scales)

ggplot(df1, aes(x = Index, y = Duration, color = as.numeric(Duration))) +
  geom_point() +
  geom_line() +
  scale_y_datetime(labels = date_format("%M:%S")) +
  scale_color_gradient("Duration", low = "#D80427", high = "#07A0FF",
                       labels = c("00", "10", "20", "30", "40"))

As suggested by @Henrik, to avoid hardcoding the labels use below:

# avoid hardcoding labels using pretty()
ggplot(df1, aes(x = Index, y = Duration, color = as.numeric(Duration))) +
  geom_point() +
  geom_line() +
  scale_y_datetime(labels = date_format("%M:%S")) +
  scale_color_gradient("Duration", low = "#D80427", high = "#07A0FF",
                       breaks = pretty(as.numeric(df1$Duration)),
                       labels = format(pretty(df1$Duration), "%M:%S"))
Community
  • 1
  • 1
zx8754
  • 52,746
  • 12
  • 114
  • 209
  • 1
    That works perfectly. My second concern was if converting to numeric preserved the relative distances between the times, and a quick test of the first two numeric values shows 1487577670 - 1487577655 = 15, which is equivalent to using the first to time values 1:10 - 00:55 = 15. So it looks like a good solution on all counts. Thanks for the help! – Mako212 Feb 20 '17 at 22:37
  • @zx8754 I think you can avoid hard-coding of the labels if you use `breaks = pretty(as.numeric(df1$Duration)), labels = format(pretty(df1$Duration), "%M:%S")` (or any `format` you desire). – Henrik Feb 20 '17 at 23:39