【问题标题】:R Plot Specify number of time tickmarks - time/date equivalent to prettyR Plot 指定时间刻度线的数量 - 时间/日期相当于漂亮
【发布时间】:2011-09-29 09:00:06
【问题描述】:

我想知道在 x 轴上绘制时间时如何绘制更多刻度线。

基本上,相当于漂亮的时间。很明显,它与时间的关系不太好,因为它使用了 1、2、5 和 10 的因子。对于时间,人们可能想要例如小时,半小时,...

plot(as.POSIXct(x,origin="1960-01-01"),y,type="l",xlab="Time")

给出的刻度线太少且间距太宽。

zoox<-zoo(y,as.POSIXct(stats$Time,origin="1960-01-01"))
plot(zoox)

给出相同的结果。

谢谢

编辑:

只是为了澄清(到目前为止的答案并没有解决我的问题):我正在寻找的是一个类似漂亮日期的功能,例如一个函数,它接受开始日期、结束日期、刻度数,并输出刻度的位置。也就是说,我很清楚可以绘制小时,绘制分钟,以及其他什么,但是相当自动化数字的刻度距离,并且日期的结果函数应该自行决定是否使用天,小时,分钟,秒、毫秒、微秒、30 分钟、500 微秒、5 秒等间隔。无论如何,这就是 pretty 对数字的作用。

EDIT2:

这是我目前用来决定时间轴格式的函数(注意这不适用于日期):

mydiff <- end-start
if(mydiff>1800) {
    axis.POSIXct(1,xrange,format="%H:%M")
} else if(mydiff>30) {
    axis.POSIXct(1,xrange,format="%H:%M:%S")
} else if(mydiff>0.5) {
    axis.POSIXct(1,xrange,format="%H:%M:%OS3")
} else
    axis.POSIXct(1,xrange,format="%H:%M:%OS6")
}

我没有增加刻度线的功能,所以我使用默认的刻度线数

【问题讨论】:

  • R 的内部函数不会考虑低于秒的时间单位。 POSIXct 类可以处理小数秒,但是围绕这个类的辅助函数通常只在第二级起作用。所以微秒间隔实际上是十进制秒并且必须手动处理。
  • @GavinSimpson:不真实,至少在我的系统上,micros 工作得很好。使用axis.POSIXct(1,xrange,format="%H:%M:%OS6") 在图表中显示它们。让我用适当的功能进行另一次编辑。虽然单位是秒,但它是一个双精度值,精度很高。
  • library(xts); ?axTicksByTimequantmod:::axTicksByTime2 做你想做的事吗?
  • @Cookie 对不起,我没有真正表达清楚。我的意思是你不能做by = "500 microseconds"; R 只理解小数秒并且在秒级别自动处理seq()axis.POSIXt() 等。

标签: r plot


【解决方案1】:

使用可重现的示例

set.seed(1)
x <- as.POSIXct(sort(sample(100000, 100)), origin="1960-01-01")
y <- rpois(100, 5)
plot(x, y, type = "l", xlab = "Time")

我们可以使用axis.POSIXct() 函数(也可以使用Axis() S3 泛型)来为绘图添加自定义轴。这里的要点是,作为用户,您可以完全控制刻度线的绘制位置和标记方式,如果默认设置不适合您,您只需要更加努力。

首先我们绘制数据,但禁止绘制 x 轴:

plot(x, y, type = "l", xlab = "Time", xaxt = "n")

接下来,我将在每个小时的开始添加一个主要刻度线。为此,我创建了一系列日期时间

  1. 来自系列中第一次观察的整整小时,
  2. 进行观察的最后一小时结束(使用 ceiling() 将我们移至下一小时),
  3. 以 1 小时 (by = "1 hour") 为单位递增序列。

这个序列被提供给axis.POSIXct()at 参数。如果不阅读?axis.POSIXct?par,其余部分应该很容易理解

## add axis tick at each hour:
axis.POSIXct(side = 1, x = x,
             at = seq(from = round(x[1], "hours"),
                      to = x[1] + ceiling(difftime(tail(x, 1), head(x, 1), 
                                                   units = "hours")),
                      by = "1 hour"),
             las = 2)

生成的图形如下所示:

为了显示更精细的控制,我现在在每个半小时位置添加小刻度线,但抑制这些刻度线的注释(通过labels 参数)并缩短小刻度线(通过图形参数tcl )。请注意seq() 方法的by 参数如何获取指定间隔的数值

## add minor ticks at 30 min intervals to above plot
axis.POSIXct(side = 1, x = x,
             at = seq(from = round(x[1], "hours"),
                      to = x[1] + ceiling(difftime(tail(x, 1), head(x, 1), 
                                                   units = "hours")),
                       by = "30 mins"),
             las = 2, tcl = -0.2, labels = FALSE)

情节现在看起来像这样:

您可以添加自己的标签,而不是 axis.POSIXct 函数提供的标签。如果你想这样做,那么我们应该将seq() 的输出分配给一个对象,然后我们可以使用format() 函数。例如:

plot(x, y, type = "l", xlab = "Time", xaxt = "n")
tseq <- seq(from = round(x[1], "hours"),
            to = x[1] + ceiling(difftime(tail(x, 1), head(x, 1), 
                                         units = "hours")),
            by = "1 hour")
axis.POSIXct(side = 1, x = x, at = tseq,
             labels = format(tseq, format = "%H:%M"), las = 2)

结果图如下所示:

format() 返回格式化日期时间的字符串。您可以 paste() 使用其他任何您想要的内容,或者查看可用于格式化 ?strftime 中的日期时间对象的其他占位符

【讨论】:

  • 很抱歉为此答案付出的努力,但您自己仍在挑选几个小时或半个小时。如果开始和结束时间之间只有 10 秒,会发生什么?举个例子,在我的特殊情况下,我有一个交互式绘图 - 使用 getGraphicsEvent() - 我可以放大绘图,并且用鼠标进一步放大,绘图轴需要慢慢从几小时切换到几分钟秒到毫秒 - 并返回,一旦我缩小。
  • 我只选择了这些时间间隔,因为您明确提到了它们。我知道 R 罐头中没有任何内容可以满足您的需求,因此您需要将我展示的自定义轴方法与 axis.POSIXct() 的黑客版本结合起来。有关这方面的指示,请参阅我的其他答案。 (即将推出)
  • 我并不反对在 R 中提出一个函数是可能的(毕竟,R 只是 C 和 C++,并且允许更多的第三方插件,所以几乎任何事情都是可能的),所有我是说到目前为止,还没有,而且我还没有时间自己写一篇。
  • 因此,另一种选择是使用您的 Edit 2 位代码,但生成我上面显示的日期时间序列,将 by 参数更改为 if else 中每个选项的合适值条款。我认为您显示的代码以及我在上面显示的自定义轴代码几乎都在那里。 axis.POSIXct() 确实做了很多你想要的,问题是它使用 pretty() 和默认值,你似乎想要改变它们(有更多的刻度等)?如果是这样,请尝试破解pretty(),如下所述。
  • 非常感谢您的这篇文章。我有 POSIXct 日期时间对象(带时间),我尝试了 axis.POSIXct(1, at = seq(min(x), max(x), by = "days"), format ="%b %d") 但这会在错误的位置生成刻度线! (我不明白为什么。似乎第一个刻度线总是向左对齐,即使第一个数据点不是在一天的开始。)我也很欣赏小刻度线代码。
【解决方案2】:

axis.POSIXct() 已经很难为轴猜测合适的漂亮值,所以我将从破解它开始。目前,它在内部依赖于将pretty() 应用于日期时间的某些功能。它使用pretty() 的默认值,因此您可以破解该函数以添加nmin.n 参数,这将增加选择的漂亮标记的数量。

axis.POSIXct() 复制到您自己的函数/文件中(给它一个新名称)。在定义中添加nmin.n 参数,默认值可能比pretty() 函数使用的值更大。并将其传递给每个pretty() 调用。

试试看。如果它工作得相当好,那么您可以执行fixInNamespace(axis.POSIXct) 对实际函数进行相同的更改,以便在调用它的所有绘图上使用它。

附:这是一个可能的黑客攻击

function (side, x, at, format, labels = TRUE, n = 5, ...) {
  mat <- missing(at) || is.null(at)
  if (!mat) 
    x <- as.POSIXct(at)
  else x <- as.POSIXct(x)
  range <- par("usr")[if (side%%2) 
    1L:2L
    else 3L:4L]
  d <- range[2L] - range[1L]
  z <- c(range, x[is.finite(x)])
  attr(z, "tzone") <- attr(x, "tzone")
  if (d < 1.1 ) {
    sc <- 0.001
    if (missing(format)) 
      format <- "%H:%M:%OS6"
  }
  else if (d < 1.1 * 30) {
    sc <- 1
    if (missing(format)) 
      format <- "%H:%M:%OS3"
  }
  else if (d < 1.1 * 60) {
    sc <- 1
    if (missing(format)) 
      format <- "%H:%M:%S"
  }
  else if (d < 1.1 * 30 * 60) {
    sc <- 60
    if (missing(format)) 
      format <- "%H:%M:%S"
  }
  else if (d < 1.1 * 60 * 60) {
    sc <- 60
    if (missing(format)) 
      format <- "%H:%M"
  }
  else if (d < 1.3 * 60 * 60 * 24) {
    sc <- 60 * 60
    if (missing(format)) 
      format <- "%H:%M"
  }
  else if (d < 2 * 60 * 60 * 24) {
    sc <- 60 * 60
    if (missing(format)) 
      format <- "%a %H:%M"
  }
  else if (d < 7 * 60 * 60 * 24) {
    sc <- 60 * 60 * 24
    if (missing(format)) 
      format <- "%a"
  }
  else {
    sc <- 60 * 60 * 24
  }
  if (d < 60 * 60 * 24 * 50) {
    zz <- pretty(z/sc,n=n)
    z <- zz * sc
    z <- .POSIXct(z, attr(x, "tzone"))
    if (sc == 60 * 60 * 24) 
      z <- as.POSIXct(round(z, "days"))
    if (missing(format)) 
      format <- "%b %d"
  }
  else if (d < 1.1 * 60 * 60 * 24 * 365) {
    z <- .POSIXct(z, attr(x, "tzone"))
    zz <- as.POSIXlt(z)
    zz$mday <- zz$wday <- zz$yday <- 1
    zz$isdst <- -1
    zz$hour <- zz$min <- zz$sec <- 0
    zz$mon <- pretty(zz$mon,n=n)
    m <- length(zz$mon)
    M <- 2 * m
    m <- rep.int(zz$year[1L], m)
    zz$year <- c(m, m + 1)
    zz <- lapply(zz, function(x) rep(x, length.out = M))
    zz <- .POSIXlt(zz, attr(x, "tzone"))
    z <- as.POSIXct(zz)
    if (missing(format)) 
      format <- "%b"
  }
  else {
    z <- .POSIXct(z, attr(x, "tzone"))
    zz <- as.POSIXlt(z)
    zz$mday <- zz$wday <- zz$yday <- 1
    zz$isdst <- -1
    zz$mon <- zz$hour <- zz$min <- zz$sec <- 0
    zz$year <- pretty(zz$year,n=n)
    M <- length(zz$year)
    zz <- lapply(zz, function(x) rep(x, length.out = M))
    z <- as.POSIXct(.POSIXlt(zz))
    if (missing(format)) 
      format <- "%Y"
  }
  if (!mat) 
    z <- x[is.finite(x)]
  keep <- z >= range[1L] & z <= range[2L]
  z <- z[keep]
  if (!is.logical(labels)) 
    labels <- labels[keep]
  else if (identical(labels, TRUE)) 
    labels <- format(z, format = format)
  else if (identical(labels, FALSE)) 
    labels <- rep("", length(z))
  axis(side, at = z, labels = labels, ...)
}

与原函数的不同之处可见here

【讨论】:

  • 很公平。最终结果证明是非常简单的 - 函数覆盖甚至可以帮助修复不正确的默认显示格式。
  • 嗯,是的,只要你对pretty() 通过因子 1、2、5 和 10 选择事物的方式感到满意。如果这让你接近但你只需要比默认更多的刻度,黑客axis.POSIXct 是要走的路。或者将其复制到您自己的函数中,进行您想要的更改,然后在编辑 2 中显示的代码中使用它。取决于您是否只想通过缩放功能绘图以使用新的启发式或 R 生成的任何绘图。跨度>
【解决方案3】:

我倾向于使用函数axis.POSIXct 和/或函数cut.POSIXt。假设您的日期向量是time,而您的值向量关联x

plot(time,x,xaxt="n")
axis.POSIXct(side=1,at=seq(min(time),max(time),by="week"),format="%d-%m") #For instance

更进一步,cut.POSIXt:

plot(time,x,xaxt="n")
axis.POSIXct(side=1,at=cut(time, breaks="week"),format="%d-%m")

【讨论】:

    【解决方案4】:

    抑制绘图中轴可用的默认值(axes = FALSE,或单个轴)并使用功能轴详细说明您想要的轴(特别是 at 参数)。见?axis

    plot(cars, axes = FALSE)
    axis( 1, at = c(5,6,7,10,11,12,21,22,23) )
    

    【讨论】:

    • 抱歉更清楚一点:Pretty 计算刻度线。来自许多请求的刻度线。或者将问题改写为您的示例,值向量来自哪里?
    • @Cookie 在我的示例中,at 是一个任意向量,表明您可以将刻度线放置在任何位置。我仍然误解你的问题吗?例如,您可以为一刻钟确定不同的刻度线大小和颜色。
    • 是的,你还是误会了。 Pretty tickmarks 需要一个随机的起点,一个随机的终点,以及许多刻度线,并会产生漂亮的刻度线。我需要的是一个函数,它接受 starttime、endtime、noOfTicks 并返回您上面引用的 at 向量 - 理想情况下也可以调整时间格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多