R Plot指定时间刻度的数量 - 时间/日期相当于漂亮

Coo*_*kie 15 plot r

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

基本上,相当于漂亮的时间.很明显,随着时间的推移不能很好地运作,因为它使用1,2,5和10的因子.对于时间,人们可能想要例如小时,半小时......

plot(as.POSIXct(x,origin="1960-01-01"),y,type="l",xlab="Time")
Run Code Online (Sandbox Code Playgroud)

给出了太少且间隔很大的标记.

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

给出了相同的.

谢谢

编辑:

只是为了澄清(到目前为止答案没有解决我的问题):我正在寻找的是一个像日期一样的函数,例如一个函数,它取一个开始日期,一个结束日期,一些滴答,并输出蜱虫的位置.也就是说,我很清楚可以绘制小时数,绘制分钟数以及其他内容,但是相当于自动化数字的刻度距离,日期的结果函数应该自行决定是否使用天,小时,分钟,秒,毫秒,微秒,30分钟,500微秒,5秒等间隔.无论如何,这就是数字的优点.

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")
}
Run Code Online (Sandbox Code Playgroud)

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

Rei*_*son 9

使用可重现的例子

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")
Run Code Online (Sandbox Code Playgroud)

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

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

plot(x, y, type = "l", xlab = "Time", xaxt = "n")
Run Code Online (Sandbox Code Playgroud)

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

  1. 系列中第一次观察的圆形小时开始,
  2. 观察的最后一小时结束时(使用ceiling()我们将我们带到下一个小时),
  3. 以1小时(by = "1 hour")为单位递增序列.

此序列提供给at参数axis.POSIXct().如果不阅读?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)
Run Code Online (Sandbox Code Playgroud)

结果图看起来像这样:

在此输入图像描述

为了显示更精细的控制,我现在在每个半小时位置添加次要刻度线,但是抑制那些刻度的注释(通过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)
Run Code Online (Sandbox Code Playgroud)

情节现在看起来像这样:

在此输入图像描述

您可以添加自己的标签,而不是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)
Run Code Online (Sandbox Code Playgroud)

结果图如下所示:

在此输入图像描述

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


Rei*_*son 7

axis.POSIXct()已经非常难以猜测轴的合适的漂亮值,所以我会从黑客入手.目前,它依赖于使用pretty()应用于日期时间的某些功能.它使用默认值,pretty()因此你可以破解函数来添加一个nmin.n参数,这将增加选择的漂亮标记的数量.

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

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

PS这是一个可能的黑客

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, ...)
}
Run Code Online (Sandbox Code Playgroud)

这里可以看到与原始功能的不同之