ggplot2:scale_x_datetime 中的小中断

ggplot2: minor breaks in scale_x_datetime

此代码:

library(lubridate)
library(ggplot2)
library(scales)
.months <- 3
.minor.intervals <- 4
.minor.intervals.num <- .months * .minor.intervals
sdate <- as.POSIXct("2015-01-01")
edate <- sdate + months(.months)
df <- data.frame(x = seq(from = sdate, to = edate,
                         length.out = .minor.intervals.num * 2),
                 y = 1:(.minor.intervals.num * 2))
p <- ggplot(df, aes(x = x, y = y))
xbm <- seq(from = sdate, to = edate, length.out = .minor.intervals.num)
p <- p + scale_x_datetime(limits = c(sdate, edate),
                          breaks = date_breaks("month"),
                          minor_breaks = xbm)
p <- p + geom_line() + geom_point()
plot(p)

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

如果我评论 minor_breaks 部分 — 一切正常。

如果我将 minor_breaks 部分更改为 minor_breaks = date_breaks("week") — 一切正常。

但我想将月份准确地分成 4 个部分...

如何解决?

我找到了解决问题的方法,但我必须承认我不确定为什么必须这样做。似乎 minor_breaks 需要数值而不是日期作为输入。

我使用以下代码创建了中断:

maj.breaks <- sdate + months(0:.months)
min.breaks <- do.call(c,
   lapply(1:.months,function(m) {
         seq(maj.breaks[m],maj.breaks[m+1],length.out = .minor.intervals+1)
   })
)

这取决于您的示例中定义的变量。请注意您定义次要休息时间的方式的不同之处:由于每个月的长度不同,因此仅将开始日期和结束日期之间的范围分成适当数量的段是不够的。您必须每个月单独拆分。

如上所述,您必须先将 min.breaks 转换为数字,然后再将其传递给 minor_breaks。我制作的情节如下:

p <- ggplot(df, aes(x = x, y = y)) +
      scale_x_datetime(limits = c(sdate, edate),
                       breaks = maj.breaks,
                       minor_breaks = as.numeric(min.breaks)) +
      geom_line() + geom_point()
plot(p)

这与您的代码相同,直到 breaksminor_breaks 的输入。无需使用向量 maj.breaks,因为您的版本也能正常工作。但我认为有趣的是 breaks 与 class POSIXct 的输入一起工作,而 minor_breaks 需要数值。不幸的是,我不知道这是什么原因。