【问题标题】:Time axis for ggplotggplot 的时间轴
【发布时间】:2019-09-26 06:24:06
【问题描述】:

我有一个时间序列(每小时)数据,我想打印该数据的选定时间段。假设我想打印从 2019 年 1 月 1 日 00:00 到 2019 年 1 月 8 日 00:00 的一周数据。我希望刻度线从 2019 年 1 月 1 日的 00:00 开始。但由于我不知道的原因,ggplot 从 03:00 开始。我错过了什么吗?

这是一个复制问题的示例代码:

library(ggplot2)
library(scales)
Sys.setenv( TZ = "GMT" )

datetime <- seq(from = as.POSIXct("2019-01-01", tz = "GMT"), length.out = 744, by = "hours")
random<- rnorm(744,100,20)

df <- data.frame(datetime,random)

time.start=as.POSIXct("2019-01-01 00:00",format="%Y-%m-%d %H:%M")
time.end=as.POSIXct("2019-01-08 00:00",format="%Y-%m-%d %H:%M")

png(filename = "test_ggplot.png", width = 800, height = 600, units = "px", pointsize = 24 )
plot.random = ggplot() + 
 geom_line(data=df, aes(x=datetime, y=random)) + 
 scale_x_datetime(limits = c(time.start,time.end),
          breaks = date_breaks("12 hours"),
          labels = date_format("%H:%M\n%d-%b")
          )
plot.random

这是图表,显示 x 轴刻度线标签从 03:00 而不是 00:00 开始。

【问题讨论】:

  • 我不确定为什么不使用数据框的第一个值作为 x 轴上的第一个值。但我找到了一个简单的解决方案。创建一个包含您想要的中断的序列seq&lt;- seq(time.start, time.end, by = 60*60*12) 并在breaks 选项中使用它ggplot() + geom_line(data=df, aes(x=datetime, y=random)) + scale_x_datetime(limits = c(time.start,time.end), breaks = seq, labels = date_format("%H:%M\n%d-%b"))

标签: r ggplot2


【解决方案1】:

我希望您的限制输入能够正常工作,这可能是一个错误。如果我删除 limits 参数并添加 expand 它似乎可以满足您的要求:

ggplot() +
  geom_line(data = df %>% head(300), aes(x = datetime, y = random)) +
  scale_x_datetime(
    #limits = c(time.start, time.end),
    breaks = date_breaks("12 hours"),
    labels = date_format("%H:%M %d-%b"),
    expand = expand_scale(0)
  ) +
  theme(axis.text = element_text(angle = 90))

【讨论】:

    【解决方案2】:

    轴标签计算发生在ggplot2:::ggplot_build.ggplot 内,这是绘制/打印 ggplot 对象时绘图构建过程的一部分。

    如果我们深入研究底层代码(这可以在调试模式下完成,从ggplot2:::ggplot_build.ggplotlayout$setup_panel_paramsself$coord$setup_panel_params 的兔子洞),我们可以看到轴标签/中断是基于轴限制所述限制已考虑任何扩展

    此轴限制计算是在 ggplot2 包中的以下(未导出)函数中完成的:

    > ggplot2:::scale_range
    function (scale, limits = NULL, expand = TRUE) 
    {
        expansion <- if (expand) 
            expand_default(scale)
        else c(0, 0)
        if (is.null(limits)) {
            scale$dimension(expansion)
        }
        else {
            range <- range(scale$transform(limits))
            expand_range(range, expansion[1], expansion[2])
        }
    }
    

    这里,将扩展量添加到代码中指定为c(time.start, time.end) 的比例限制。实际的扩展量取决于参数的组合:

    案例 1:如果 expand 为 TRUE

    扩展量取决于与比例关联的默认扩展,在ggplot2:::expand_default中计算:

    1. 如果指定了刻度的扩展因子,则扩展量采用该值向量;
    2. 否则,扩展量将采用默认的c(0, 0.6, 0, 0.6) 用于离散规模,c(0.05, 0, 0.05, 0) 用于连续规模。

    情况 2:如果 expand 为 FALSE

    扩展量被硬编码为c(0, 0)

    因此,要为轴中断/标签计算保留所需的比例限制c(time.start, time.end),必须满足以下两个条件之一:

    1. 比例的扩展因子指定为c(0, 0)(根据@yake84 的回答);
    2. expand 的输入值为 FALSE——取自绘图对象坐标系中的expand 参数(默认为coord_cartesian)。

    总之,以下任一项都会为您提供相同的 x 轴标签:

    p <- ggplot() + 
      geom_line(data = df, aes(x = datetime, y = random)) +
      # increase margin on the right to accommodate axis label right at the end
      theme(plot.margin = unit(c(5.5, 20, 5.5, 5.5), "pt")) 
    
    # specify 0 expansion factor in scale
    p +
      scale_x_datetime(limits = c(time.start, time.end),
                       breaks = date_breaks("12 hours"),
                       labels = date_format("%H:%M\n%d-%b"),
                       expand = c(0, 0))
    
    # specify no expansion in coord (note this affects y-axis too)
    p +
      scale_x_datetime(limits = c(time.start, time.end),
                       breaks = date_breaks("12 hours"),
                       labels = date_format("%H:%M\n%d-%b")) +
      coord_cartesian(expand = FALSE)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-10
      • 2017-03-17
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 2011-11-25
      相关资源
      最近更新 更多