【问题标题】:Time of day - day distribution of episodes plot情节情节的一天中的时间分布
【发布时间】:2012-09-12 13:33:16
【问题描述】:

我正在测量某些工作站中某一集的持续时间。我有剧集开始和剧集结束的时间戳。我想画一个图,y 轴是一天中的时间,x 轴是观察日。任何想法我怎么能做到这一点?

例如我有

    id  start               end
    1   01/01/2010 10:00:00 02/01/2010 22:00:00
    1   04/01/2012 08:00:00 04/01/2012 14:00:00

我想构建一个像附件一样的情节

有什么想法可以做到这一点吗?与所附图表不同,我希望在图表中具有微小的准确性/表示。

非常感谢

【问题讨论】:

    标签: r


    【解决方案1】:

    首先,您的示例数据不可重现;我假设日期是日/月/年,但如图所示很难说。此外,日期类型在 R 中是特殊的,因此了解您的日期类型很重要。因此,首先,我将创建一个类似的可重现数据集:

    DF <-
    structure(list(id = c(1L, 1L), start = structure(c(1262340000, 
    1262592000), class = c("POSIXct", "POSIXt"), tzone = "GMT"), 
        end = structure(c(1262469600, 1262613600), class = c("POSIXct", 
        "POSIXt"), tzone = "GMT")), .Names = c("id", "start", "end"
    ), row.names = c(NA, -2L), class = "data.frame")
    

    看起来像

    > DF
      id               start                 end
    1  1 2010-01-01 10:00:00 2010-01-02 22:00:00
    2  1 2010-01-04 08:00:00 2010-01-04 14:00:00
    

    现在,要绘制这个,我们需要做几个转换。日期和时间必须分开,因为它们被绘制在不同的轴上。

    library("chron")
    library("plyr")
    DF$start.day <- as.Date(DF$start)
    DF$end.day <- as.Date(DF$end)
    DF$start.time <- as.chron(DF$start) - floor(as.chron(DF$start))
    DF$end.time <- as.chron(DF$end) - floor(as.chron(DF$end))
    

    此外,日期必须转换为经过的日期。

    t0 <- min(DF$start.day, DF$end.day)-1
    DF$start.monitored.day <- as.numeric(DF$start.day - t0)
    DF$end.monitored.day <- as.numeric(DF$end.day - t0)
    

    最后,跨越午夜的时间段必须分成多个范围,以便每个范围都包含在给定的一天内。这一步不是很简单。

    DF$index <- seq_len(nrow(DF))
    DF <- ddply(DF, .(index), function(df) {
      if(df$start.monitored.day == df$end.monitored.day) {
        df 
      } else {
        data.frame(start.monitored.day = df$start.monitored.day : df$end.monitored.day,
                   end.monitored.day = df$start.monitored.day : df$end.monitored.day,
                   start.time = c(df$start.time, rep(times("00:00:00"), df$end.monitored.day-df$start.monitored.day)),
                   end.time = times(c(rep(times("23:59:59"), df$end.monitored.day-df$start.monitored.day), df$end.time)),
                   id = df$id,
                   index = df$index)
      }
    })
    

    现在数据是可以绘制的格式了。

    > DF[c("start.monitored.day", "end.monitored.day", "start.time", "end.time")]
      start.monitored.day end.monitored.day start.time end.time
    1                   1                 1   10:00:00 23:59:59
    2                   2                 2   00:00:00 22:00:00
    3                   4                 4   08:00:00 14:00:00
    

    我将使用ggplot 来绘制这个,因为我更熟悉它并且因为我已经完成了一些previous work on time scales with it

    取自那篇博文

    library("ggplot2")
    library("scales")
    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())
    }
    

    只留下实际情节

    ggplot(DF) +
      geom_rect(aes(xmin = start.monitored.day - 0.5,
                    xmax = start.monitored.day + 0.5, 
                    ymin = start.time,
                    ymax = end.time)) +
      scale_y_times("Time") +
      scale_x_continuous("Monitored day")
    

    【讨论】:

    • 非常感谢。使用 base R 也可以实现类似的功能吗?
    • @ECII 我确信这是可能的,但我对基本图形并不精通,所以我不知道如何处理它。我会把它留给其他人来解决。
    猜你喜欢
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2019-12-05
    • 1970-01-01
    相关资源
    最近更新 更多