Tres variables deben ser visualizadas: tiempo, zona y lado. Deberíamos aprovechar las dos coordenadas cartesianas de la gráfica para mapear dos de estas. Luego se necesitará alguna cualidad gráfica --símbolo, color, claridad o orientación-- para simbolizar la tercera.
Para ayudar al ojo a seguir la secuencia temporal puede ser útil conectar los símbolos con segmentos de línea tenues. Podemos obtener un poco más de información al borrar los segmentos que parezcan corresponder a quiebres en la serie.
La primera solución utiliza el tipo de símbolo y color para distinguir los lados, la posición vertical para identificar las zonas, y la posición horizontal para el tiempo. Está diseñada para mostrar el progreso de la zona y el lado con el tiempo para ayudar a visualizar las transiciones. Para clarificar las superposiciones, el símbolo para el lado 2 se posiciona arriba de su ubicación nominal y el símbolo para el lado 1 se posiciona abajo de su ubicación nominal.
Esta figura hace evidente de inmediato que la Guardia 2 prefiere el lado azul (lado 1) sobre el rojo (lado 2) y que se mueve alrededor de las zonas con más frecuencia y de manera más regular.
El uso de ejes de tiempo idénticamente escalados y orientados en estas gráficas paralelas permite la comparación visual de los patrones de patrullaje del guardia durante cualquier intervalo de tiempo. Con muchos guardias, esta construcción se presta bien para mostrar todos los datos simultáneamente en un "múltiple pequeño".
La segunda solución utiliza el color del símbolo para distinguir los tiempos, la posición vertical para identificar los lados, y la posición horizontal para la zona. Es una visualización tipo mapa (que se generalizaría a un diseño espacial más complejo). Esto podría utilizarse para estudiar las frecuencias con las que cada espacio es visitado por cada guardia y, de manera más limitada, visualizar los movimientos entre los espacios.
Las diferentes frecuencias con las que las zonas y lados fueron visitados se muestran claramente en esta figura. La falta de visita de la Guardia 2 al lado 2 de la zona 10 es inmediatamente evidente, mientras que no era evidente en la primera figura.
Estas figuras fueron producidas en R
. La estructura de datos de entrada es una lista de vectores paralelos para los tiempos, zonas y lados: uno por guardia. El siguiente código comienza generando algunos datos de muestra aleatoriamente. Se proporcionan dos funciones para hacer la gráfica para un guardia dado, correspondientes a las figuras.
#
# Matrices de transición de lados
#
transicion.lado <- function(izquierda=1/2, derecha=1/2) {
rbind(c(izquierda, 1-izquierda), c(1-derecha, derecha))
}
#
# Matrices de transición de zonas
#
transicion.zona <- function(n, arriba=1/2, quedarse=0, abajo=(1-arriba-quedarse)) {
x <- rep(c(abajo, quedarse, arriba, rep(0, n-2)), n)
q <- matrix(x[-c(1, 2:n+n^2)], n)
q <- q / apply(q, 1, sum)
return (q)
}
n.zonas <- 10
guardias <- list(list(lado=transicion.lado(1/2,1/2),
zona=transicion.zona(n.zonas,1/2,0)),
list(lado=transicion.lado(3/4,1/4),
zona=transicion.zona(n.zonas,1/8,3/4)))
#
# Crear caminatas de cadena de Markov para todos los guardias.
#
n.pasos <- 500
caminatas <- list()
for (g in guardias) {
zona <- integer(n.pasos)
lado <- integer(n.pasos)
# Ubicación inicial aleatoria
zona[1] <- sample.int(n.zonas, 1)
lado[1] <- sample.int(2, 1)
for (i in 2:n.pasos) {
zona[i] <- sample.int(n.zonas, 1, prob=g$zona[zona[i-1],])
lado[i] <- sample.int(2, 1, prob=g$lado[lado[i-1],])
}
s <- cumsum(sample(c(rexp(n.pasos-3), rexp(3, 10/n.pasos))))
caminatas <- c(caminatas, list(list(zona=zona, lado=lado, tiempo=s/max(s))))
}
#
# Mostrar una caminata.
#
grafico.caminata <- function(caminata, ...) {
n <- length(caminata$zona)
#
# Encontrar diferencias de tiempo atípicas.
#
d <- diff(caminata$tiempo)
q <- quantile(d, c(1/4, 1/2, 3/4))
umbral <- q[2] + 5 * (q[3]-q[1])
quiebres <- unique(c(which(d > umbral), n))
#
# Graficar los datos.
#
simbolo <- c(0, 19)
col <- c("#2020d080", "#d0202080")
plot(caminata$tiempo, caminata$zona, type="n", xlab="Tiempo", ylab="Zona", ...)
j <- 1
for (i in quiebres) {
lines(caminata$tiempo[j:(i-1)], caminata$zona[j:(i-1)], col="#00000040")
j <- i+1
}
points(caminata$tiempo, caminata$zona+0.2*(caminata$lado-3/2), pch=simbolo[caminata$lado], col=col[caminata$lado],
cex=min(1,sqrt(200/n)))
}
grafico.caminata2 <- function(caminata, n.zonas=10, n.lados=2, ...) {
n <- length(caminata$zona)
#
# Encontrar diferencias de tiempo atípicas.
#
d <- diff(caminata$tiempo)
q <- quantile(d, c(1/4, 1/2, 3/4))
umbral <- q[2] + 5 * (q[3]-q[1])
quiebres <- unique(c(which(d > umbral), n))
#
# Graficar el mapa de referencia
#
col <- "#3050b0"
plot(c(1/2, n.zonas+1/2), c(1/2, n.lados+1/2), type="n", bty="n", tck=0,
fg="Blanco",
xaxp=c(1,n.zonas,n.zonas-1), yaxp=c(1,n.lados,n.lados-1),
xlab="Zona", ylab="Lado", ...)
polygon(c(1/2,n.zonas+1/2,n.zonas+1/2,1/2,1/2), c(1/2,1/2,n.lados+1/2,n.lados+1/2,1/2),
border=col, col="#fafafa", lwd=2)
for (i in 2:n.zonas) lines(rep(i-1/2,2), c(1/2, n.lados+1/2), col=col)
for (i in 2:n.lados) lines(c(1/2, n.zonas+1/2), rep(i-1/2,2), col=col)
#
# Graficar los datos.
#
col <- terrain.colors(n, alpha=1/2)
x <- caminata$zona + runif(n, -1/3, 1/3)
y <- caminata$lado + runif(n, -1/3, 1/3)
j <- 1
for (i in quiebres) {
lines(x[j:(i-1)], y[j:(i-1)], col="#00000020")
j <- i+1
}
points(x, y, pch=19, cex=min(1,sqrt(200/n)), col=col)
}
par(mfcol=c(length(guardias), 1))
i <- 1
for (g in caminatas) {
grafico.caminata(g, main=paste("Guardia", i))
i <- i+1
}
i <- 1
for (g in caminatas) {
grafico.caminata2(g, main=paste("Guardia", i))
i <- i+1
}