R Plot Укажите количество отметок времени - время / дата, эквивалентное довольно - PullRequest
15 голосов
/ 06 июля 2011

Мне было интересно, как я могу нанести больше отметок при нанесении времени на ось 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 секунд и т. д.В любом случае, это то, что довольно красиво для чисел.

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")
}

У меня нет функции увеличения тиковых меток, поэтому я использую количество тиковых меток по умолчанию

Ответы [ 4 ]

9 голосов
/ 05 июля 2012

Используя воспроизводимый пример

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")

Далее я добавляю большую галочку в начале каждого часа.Для этого я создаю последовательность datetime, которая идет от

  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)

Получившийся рисунок выглядит следующим образом:

enter image description here

ПоказатьДля более точного управления я теперь добавляю незначительные отметки в каждом получасовом местоположении, но подавляю аннотацию этих отметок (с помощью аргумента labels), а также делаю меньшие отметки (с помощью графического параметра tcl).Обратите внимание, как аргумент by метода seq() может принимать числовую величину указанного интервала

## 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)

Теперь график выглядит так:

enter image description here

Вы можете добавлять свои собственные метки, а не те, которые предлагает функция 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)

Полученный график показан ниже:

enter image description here

format() возвращает строку символов отформатированной даты-времени.Вы можете paste() на любом другом месте или посмотреть на другие заполнители, которые можно использовать для форматирования объектов даты и времени в ?strftime

7 голосов
/ 05 июля 2012

axis.POSIXct() уже работает достаточно усердно, чтобы угадать подходящие симпатичные значения для оси, поэтому я начну с этого.На данный момент он основан на использовании pretty(), примененном к некоторой функции datetime.Он использует значения по умолчанию для pretty(), так что вы можете взломать функцию, чтобы добавить аргумент n или min.n, который увеличит количество выбранных красивых отметок.

Скопируйте axis.POSIXct() в вашу собственную функцию /файл (дать ему новое имя).Добавьте в определение аргумент n или min.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, ...)
}

Различия с исходной функцией можно увидеть здесь

3 голосов
/ 05 июля 2012

Я склонен использовать функцию 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")
0 голосов
/ 06 июля 2011

Подавите значения по умолчанию, доступные для оси на графике (axes = FALSE, или отдельной оси), и используйте ось функции, чтобы детализировать, что вы хотите для оси (в частности, аргумент at). см ?axis

plot(cars, axes = FALSE)
axis( 1, at = c(5,6,7,10,11,12,21,22,23) )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...