2011-07-06 6 views
15

Me preguntaba cómo podría trazar más marcas al trazar el tiempo en el eje x.R Trazar Especifique el número de marcas de tiempo: hora/fecha equivalente a bonita

Básicamente, un tiempo equivalente a bastante. Obviamente, no funciona tan bien con los tiempos, ya que usa factores de 1, 2, 5 y 10. Por tiempo uno probablemente quiera, p. horas, medias horas, ...

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

da realmente muy pocos y muy espaciados tickmarks.

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

da lo mismo.

Gracias

EDIT:

sólo para aclarar (respuestas hasta el momento no se ocupan de mi problema): Lo que estoy buscando es una función como bonito para las fechas, por ejemplo, una función, que toma una fecha de inicio, una fecha de finalización, un número de tics y genera la ubicación de los tics. Es decir, soy consciente de que es posible trazar horas, trazar los minutos, y qué más, pero bastante automatiza la distancia de tics para los números, y una función resultante para las fechas debería decidir por sí misma si usar días, horas, minutos, segundo, milisegundos, microsegundos, 30 minutos, 500 micros, 5 segundos, etc. intervalos. Eso es lo que hace bastante para los números, de todos modos.

Edit2:

Ésta es la función que utilizo actualmente para decidir el formato para el eje de tiempo (tenga en cuenta que esto no funciona para las fechas):

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

que no tienen una función que aumenta las marcas, así que uso el número predeterminado de marcas

+0

las funciones internas del R no tendrá en cuenta las unidades de tiempo menor que el segundo. La clase 'POSIXct' puede ocuparse de segundos decimales, pero las funciones auxiliares alrededor de esta clase generalmente solo funcionan en el segundo nivel. Entonces, el intervalo de microsegundos realmente estará en segundos decimales ** y ** deben manejarse a mano. –

+0

@GavinSimpson: Untrue, al menos en mi sistema de micros funcionan perfectamente. Utilice 'axis.POSIXct (1, xrange, format ="% H:% M:% OS6 ")' para mostrarlos en el gráfico. Déjame hacer otra edición con una función apropiada. Mientras que la unidad es segundos, es un valor doble y tiene una precisión bastante alta. – Cookie

+0

Hace 'library (xts); ? axTicksByTime', o 'quantmod ::: axTicksByTime2' hacer lo que quieras? – GSee

Respuesta

7

axis.POSIXct() ya funciona bastante difícil de adivinar valores bastante adecuados para el eje, por lo que me gustaría empezar por el pirateo de eso. Por el momento, confía internamente en el uso de pretty() aplicado a alguna función de las fechas y horas. Utiliza los valores predeterminados para pretty() por lo que podría hackear la función para agregar un argumento n o min.n que aumentaría el número de marcas bonitas seleccionadas.

Copie axis.POSIXct() en su propia función/archivo (asígnele un nuevo nombre).Agregue un argumento n o min.n a la definición, probablemente con valores mayores como valores predeterminados que los utilizados por la función pretty(). Y pase eso a cada una de las pretty() llamadas que se realizan.

Pruébelo. Si funciona razonablemente bien, puede hacer fixInNamespace(axis.POSIXct) para realizar los mismos cambios en la función real, de modo que se use en todos los trazados a los que se llame.

P.S. Aquí es un posible corte

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, ...) 
} 

Diferencias con la función original se puede ver here

+0

Bastante justo. Resulta ser bastante simple, entonces, al final, una anulación de función incluso ayudaría a corregir los formatos de visualización predeterminados incorrectos. – Cookie

+0

Bueno, sí, siempre y cuando estés contento con la forma 'bonita()' elige las cosas a través de los factores 1, 2, 5 y 10. Si eso te acerca pero solo necesitas más tics que los predeterminados, piratear 'axis.POSIXct 'es el camino a seguir. O cópielo en su propia función, realice los cambios que desee y, en su lugar, utilícelos en el código que muestra en Editar 2. Depende de si solo desea trazar a través de su función de zoom para usar la nueva heurística o cualquier trama producida por R. –

0

Suprima los valores predeterminados disponibles para el eje en el gráfico (axes = FALSE, o eje individual) y utilice el eje de la función para detallar lo que desea para el eje (específicamente el at argumento). veo ?axis

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

Perdón por ser más claro: calcula bastante las marcas. A partir de una serie de marcas solicitadas. O para reformular la pregunta a su ejemplo, ¿de dónde viene eso en el vector de valores? – Cookie

+0

@Cookie En mi ejemplo, at es un vector arbitrario para mostrar que puede colocar las marcas 'en' cualquier ubicación. ¿Todavía no entiendo tu pregunta? Podría determinar un tamaño y color de marca diferente para los cuartos de hora, por ejemplo. –

+0

Sí, todavía lo malinterpretas. Pretty tickmarks toma un punto de partida aleatorio, y un punto final aleatorio, y un número de tickmarks, y sale con los bonitos. Lo que necesito es una función que tome starttime, endtime, noOfTicks y devuelva el vector que cita arriba, idealmente ajustando también el formato de la hora. – Cookie

3

que tienden a utilizar la función axis.POSIXct y/o función cut.POSIXt. Digamos que su vector de fecha es time y su vector de valor asociada x:

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

Y, yendo más allá, con cut.POSIXt:

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

Utilizando un ejemplo reproducible

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

nos puede hacer uso de la función axis.POSIXct() (también se podría usar el Axis() S3 genérico) para agregar un hacha personalizada es a la trama. El punto principal aquí es que usted, el usuario, tiene el control total de dónde se dibujan los ticks y cómo están etiquetados, solo necesita trabajar un poco más si los valores predeterminados no funcionan; t funcionan para usted.

Primero graficamos los datos, sino suprimir dibujo del eje x:

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

que viene voy a añadir una marca importante señal al comienzo de cada hora. Para esto crear una secuencia de datetimes que va

  1. de la hora redondeada de la primera observación de la serie,
  2. a el final de la última hora en la que se hizo una observación (usando ceiling() para pasarnos a la próxima hora),
  3. incrementando la secuencia en unidades de 1 hora (by = "1 hour").

Esta secuencia se suministra al argumento at de axis.POSIXct(). El resto debe ser fácil de seguir si no se lee ?axis.POSIXct y ?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) 

La cifra resultante es el siguiente:

enter image description here

Para mostrar un control más preciso, añado ahora las marcas de graduación de menor importancia en cada mitad -la ubicación, pero suprima la anotación de esos tics (a través del argumento labels) y también hace que los tics menores sean más cortos (a través del parámetro de gráficos tcl). Observe cómo el argumento del método seq()by puede tomar una cantidad numérica del intervalo indicado

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

La trama ahora se ve así:

enter image description here

Puede añadir sus propias etiquetas en lugar de los que la función axis.POSIXct viene con. Si desea hacer esto, entonces deberíamos asignar la salida de seq() a un objeto que luego podemos usar la función format(). Por ejemplo:

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) 

Se muestra la gráfica resultante a continuación:

enter image description here

format() devuelve una cadena de caracteres de la fecha y hora con formato. Puede paste() en cualquier otra cosa que desee o mirar a los otros marcadores de posición que se pueden utilizar para dar formato a los objetos de fecha y hora en ?strftime

+0

Disculpa el esfuerzo realizado en esta respuesta, pero sigues eligiendo horas o medias horas. ¿Qué pasaría si solo hubiera 10 segundos entre el inicio y el final? Para darles un ejemplo, en mi caso particular, tengo un gráfico interactivo, usando 'getGraphicsEvent()', donde puedo acercarme a la gráfica, y cuanto más hago zoom con el mouse, el eje de la gráfica necesita cambiar lentamente de horas a minutos a segundos a milisegundos, y viceversa, una vez que retrocedo. – Cookie

+0

Solo elegí esos intervalos de tiempo porque * explícitamente * los mencionó. No hay nada en R enlatado del que tenga conocimiento que haga lo que quiera, así que necesitará combinar el enfoque del eje personalizado que muestro con una versión pirateada de 'axis.POSIXct()'. Ver mi otra respuesta para los indicadores sobre eso. (Próximamente) –

+0

No estoy disputando que es posible encontrar una función en R (después de todo, R es solo C y C++, y permite más complementos de terceros, por lo que prácticamente todo es posible), todo lo que digo que hasta el momento, no hay nada por ahí, y no he encontrado el tiempo para escribir uno yo mismo. – Cookie

Cuestiones relacionadas