ggplot2:scale_x_datetime

时间:2015-05-26 13:17:12

标签: r ggplot2

此代码:

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个月分成4个部分......

如何解决?

1 个答案:

答案 0 :(得分:2)

我找到了解决问题的方法,但我必须承认,我不确定为什么必须这样做。似乎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适用于类POSIXct的输入,而minor_breaks需要数值。不幸的是,我不知道原因。

enter image description here