placing times on y-axis in ggplot2

198 views
Skip to first unread message

Mike Dylan

unread,
May 1, 2013, 9:44:21 PM5/1/13
to ggp...@googlegroups.com
I have a data frame like this:

dput(head(t,30))

    structure(list(DATE = structure(c(15744, 15744, 15744, 15744, 
    15744, 15744, 15744, 15744, 15744, 15744, 15744, 15744, 15744, 
    15744, 15744, 15744, 15744, 15744, 15744, 15744, 15744, 15744, 
    15744, 15744, 15744, 15744, 15744, 15744, 15744, 15744), class = "Date"), 
        TIME1 = c("00:14", "00:29", "00:44", "00:59", "01:14", "01:29", 
        "01:44", "01:59", "02:14", "02:29", "02:44", "02:59", "03:14", 
        "03:29", "03:44", "03:59", "04:14", "04:29", "04:44", "04:59", 
        "05:14", "05:29", "05:44", "05:59", "06:14", "06:29", "06:44", 
        "06:59", "07:14", "07:29"), CPU = c(27.7058823529412, 28.1, 
        25.5444444444444, 24.4333333333333, 25.3222222222222, 22.3666666666667, 
        20.8555555555556, 19.5777777777778, 20.8555555555556, 20.0333333333333, 
        19.1888888888889, 18.5444444444444, 19.3333333333333, 19.0222222222222, 
        17.3111111111111, 17.2777777777778, 17.2777777777778, 17.1555555555556, 
        17.2333333333333, 17.3777777777778, 17.5444444444444, 18.2222222222222, 
        17.7444444444444, 18.6333333333333, 21.6333333333333, 23.9, 
        27.9666666666667, 28.5222222222222, 32.1777777777778, 33.0111111111111
        )), .Names = c("DATE", "TIME1", "CPU"), row.names = c(NA, 
    30L), class = "data.frame")

I am trying to create a ggplot that will have DATE on x-axis and TIME1 on the y-axis. Currently, If I try to plot it, I see all the values of TIME1 on the y-axis and making it very difficult to read the graph. 

Is there a way to scale TIME1 on y-axis?

as hightlighted on the blog post (http://blog.ggplot2.org/post/29433173749/defining-a-new-transformation-for-ggplot2-scales-part), I have done the following:

    t$TIME<-times(t$TIME1)
    
    times_trans <- function() {
        fmt <- function(x) {
            format(x, simplify = !any(diff(x) < 1/(24*60)))
        }
        trans_new("chrontimes",
                  transform = as.numeric,
                  inverse = times,
                  breaks = pretty_breaks(),
                  format = fmt,
                  domain=c(0,1))
    }
    
    
    timesreverse_trans <- function() {
        trans <- function(x) {-as.numeric(x)}
        inv <- function(x) {times(-x)}
        fmt <- function(x) {format(x, simplify = !any(diff(x) < 1/(24*60)))}
        trans_new("chrontimes-reverse",
                  transform = trans,
                  inverse = inv,
                  breaks = pretty_breaks(),
                  format = fmt,
                  domain=c(0,1))
    }
    
    
    scale_y_times <- function(..., trans=NULL) {
        scale_y_continuous(trans=timesreverse_trans(), ...)
    }

THEN 

When I do this:

    ggplot(t,aes(DATE, TIME1, group=SERVER, fill=CPU)) + geom_tile() + facet_wrap(~SERVER) +scale_y_times()

I get values from 00:00, 00:25, 00:50, 00:75, 1 values on the y-axis. Any ideas what I might be missing here?

when I compare Brian Diggs post dat data frame with mine, they are identical:

    str(t)
    'data.frame':   55076 obs. of  4 variables:
     $ TIME  :Class 'times'  atomic [1:55076] 0.0101 0.0205 0.0309 0.0413 0.0517 ...
      .. ..- attr(*, "format")= chr "h:m:s"
     $ CPU   : num  27.7 28.1 25.5 24.4 25.3 ...
     $ SERVER: chr  "cigp04a4a002" "cigp04a4a002" "cigp04a4a002" "cigp04a4a002" ...
     $ DATE  : Date, format: "2013-02-08" "2013-02-08" "2013-02-08" "2013-02-08" ...

 \n

    str(dat)
    'data.frame':   11 obs. of  2 variables:
     $ time :Class 'times'  atomic [1:11] 0.776 0.702 0.629 0.556 0.482 ...
      .. ..- attr(*, "format")= chr "h:m:s"
     $ value: int  7 6 9 11 10 1 4 2 3 5 ...

when I do graph his dat data frame I do get the Hour and Minute on the y-axis. when I try to graph my t data frame, y-axis is from 0.00, 0.25, 0.50, 0.75 and 1.0.

Brian Diggs

unread,
May 2, 2013, 11:50:12 AM5/2/13
to Mike Dylan, ggplot2
I finally got around to posting an answer to you question on
StackOverflow: http://stackoverflow.com/q/16238010/892313

I think you might be seeing a bug that I later found in my blog post
code; there was a problem if the range of times (or, specifically, the
range of breaks) included midnight as 24:00 (which is reasonable for a
break label even if a time can't be that).

You can get a pure times object with

t$TIME<-times(paste0(t$TIME1,":00"))

The updated code for the transformer is then

timesreverse_trans <- function() {
trans <- function(x) {-as.numeric(x)}
inv <- function(x) {times(-x)}
fmt <- function(x) {
notone <- x != 1
simplify <- !any(diff(x) < 1/(24*60))
ifelse(notone,
format(x-floor(x), simplify=simplify),
ifelse(simplify, "24:00", "24:00:00"))
}
trans_new("chrontimes-reverse",
transform = trans,
inverse = inv,
breaks = pretty_breaks(),
format = fmt,
domain=c(0,1))
}
scale_y_times <- function(..., trans=NULL) {
scale_y_continuous(trans=timesreverse_trans(), ...)
}

and

ggplot(t,aes(DATE, TIME, fill=CPU)) + geom_tile() + scale_y_times()

gives a plot with the right y scale (I removed references to SERVER
since it wasn't in your example data frame).


--
Brian S. Diggs, PhD
Senior Research Associate, Department of Surgery
Oregon Health & Science University
Reply all
Reply to author
Forward
0 new messages