Trazado excesivo de puntos en mapas en R (por ejemplo, con ggplot2): ¿cómo empujar los puntos hacia un lado, marcar posiciones originales, combinar puntos cercanos ...?


12

Tengo una base de datos que contiene idiomas, sus longitudes y latitudes y un valor de característica (ya sea categoría 1, categoría 2 o ambas; en la gráfica, estos están marcados en rojo, azul y verde, respectivamente). Puede haber hasta tres puntos por idioma y, naturalmente, dos puntos de idioma pueden estar muy cerca uno del otro.

    name            longitude   latitude    sp_sum
1   Modern Armenian 45          40          both
2   Modern Armenian 45          40          both
3   Modern Armenian 45          40          spatial
4   Dieri           138         -28.1667    both
5   Dieri           138         -28.1667    both
6   Finnish         25.5577     64.7628     non-spatial
7   Crimean Tatar   28.1418     43.8398     spatial
8   Ese Ejja        -67.515     -11.7268    non-spatial
9   Makhuwa         38.8052     -14.8509    non-spatial
...

Estoy usando el paquete R ggplot2 (ese es el que estoy más familiarizado, así que me encantaría seguir usándolo, pero otras soluciones también son bienvenidas). Aquí hay un recorte de un intento anterior (código: ver abajo 1 ):

Recorte del intento anterior

Para cada punto, me gustaría que la posición (aproximada), así como el valor, aún estén visibles. (Si hay varios puntos para un solo idioma, se pueden combinar).

¿Hay alguna forma de ...?

  • ... para mover los puntos hacia un lado lo suficiente como para que no haya exceso de trazado (menos al azar que, digamos, al usar geom_jitter, por ejemplo, hay mucho de ese tipo de esquiva en el paquete de abejas ).
  • ... y / o tener algún tipo de "línea" apuntando a la posición original de un punto si tuviera que ser movido?
  • ... o para combinar puntos cercanos de una manera que todavía estén claros (probablemente existe una técnica de trabajo que utiliza binning, es decir, stat_bin * o algo con un efecto similar)?
  • ... o para crear una "trama interactiva" como las que se ven en sitios web que aún se pueden incluir en un pdf (estoy pensando también en las capacidades de paquetes como animación y brillo aquí)? Por ejemplo, se ve así en wals.info :

    Wals

De una publicación anterior aquí, sé que el paquete directlabels puede mover etiquetas, pero no he encontrado una manera de hacerlo mover los puntos también.

¡No dude en pedir una aclaración!

Nota: Soy consciente de que ha habido una serie de preguntas sobre el trazado excesivo, pero las que he investigado parecen tener un propósito diferente (es decir, estadístico) (no pretendo haberlo leído todo , así que ' estaría encantado de aceptar un enlace también, por supuesto). Intentaré enumerar las publicaciones que conozco y que pueden ser relevantes (por lo que he leído, ninguna de estas responde exactamente a mi pregunta).


1 Las siguientes líneas de código crearon el recorte desde arriba.

library(OpenStreetMap)
library(ggplot2)

data <- read.csv(header = T, sep = ",", dec = ".", quote= "'",
text = "'','name','longitude','latitude','sp_sum'
'1','Modern Armenian',45,40,'both'
'2','Modern Armenian',45,40,'both'
'3','Modern Armenian',45,40,'spatial'
'4','Dieri',138,-28.1667,'both'
'5','Dieri',138,-28.1667,'both'
'6','Finnish',25.5577,64.7628,'non-spatial'
'7','Crimean Tatar',28.1418,43.8398,'spatial'
'8','Sochiapam Chinantec',-96.6079,17.7985,'non-spatial'
'9','Ese Ejja',-67.515,-11.7268,'non-spatial'
'10','Makhuwa',38.8052,-14.8509,'non-spatial'
'11','Mualang',111.077,0.31083,'non-spatial'
'12','Martuthunira',116.607,-20.9294,'non-spatial'
'13','Evenki',108.626,53.85,'both'
'14','Afrikaans',30,-22,'both'
'15','Male (Ethiopia)',36.9892,5.91975,'both'
'16','Manchu',126.557,47.3122,'both'
'17','Dime',36.3329,6.20951,'non-spatial'
'18','Koorete',37.8679,5.80545,'non-spatial'
'19','Wolaytta',37.7537,6.32668,'both'
'20','Dizin',35.5763,6.1405,'both'")

map <- openproj(openmap(c(85, -179.9), c(-60, 179.9), zoom = 2, type = "nps"))
plot <- autoplot(map) + 
  geom_point(data = data, aes(x = longitude, y = latitude),
             color = "white", alpha = 0.8, size = 8) +
  geom_point(data = data, aes(x = longitude, y = latitude, color = sp_sum),
             alpha = 0.3, size = 4)
plot

¿Hay algo que pueda mejorar para que la pregunta sea más fácil de entender y responder? ¡Por favor, déjame saber si tienes algunas ideas!
maj

1
Esta no es una pregunta con la que tenga habilidades relevantes para ayudar, pero la he votado para que parezca un poco más alta en algunas listas. Si no recibe ningún comentario que ayude a mejorarlo, y en cualquier caso, le recomiendo revisarlo / revisarlo a intervalos frecuentes teniendo en cuenta los consejos ofrecidos en meta.gis.stackexchange.com/a/3353
PolyGeo

Creo que es posible que desee utilizar alguna funcionalidad gráfica dirigida por la fuerza. No estoy seguro de cómo hacerlo y mantener algunos puntos anclados, pero lo que estoy pensando es identificar todos los grupos (por alguna función de agrupación de proximidad) y usar el centroide del grupo como un ancla y dejar que sus miembros floten (y no trazar el centroide en sí mismo, solo usarlo para anclar los vértices conectados en su pequeño gráfico). Y, por supuesto, si alguno de los grupos tiene un solo miembro, estos también deberían estar anclados a su ubicación.
aaryno

No seguí el lado en "... nuevamente parece que solo se aplica a los diagramas de dispersión", porque este es un diagrama de dispersión.
whuber

Admito que debo haber usado un término incorrecto; lo que quise decir con diagrama de dispersión fue el diagrama de dispersión estadístico típico donde la posición generalmente es menos importante que en el tipo de diagrama que tenemos aquí (= un mapa; si los puntos se mueven aquí, es obvio inmediatamente).
maj

Respuestas:


2

Hasta ahora solo he encontrado una solución bastante decente: el paquete packcircles R puede haber sido diseñado para otro propósito, pero hace un buen trabajo alejando los puntos unos de otros (también vea la publicación de blog correspondiente ). Es posible que no entienda todo el funcionamiento interno de este paquete, pero afortunadamente, como verá, el archivo de ejemplo del sitio web se puede usar casi directamente: todo lo que necesita cambiar son los nombres de las variables, la distancia entre los círculos (o puntos , dependiendo de las funciones que utilice) y los "límites" del gráfico (es decir, 180 °).

(Al final, todo se reduce a la circleLayout()función, que toma un marco de datos con columnas de longitud, lat y radio (es decir, distancia) y dos vectores xlim / ylim de 2 números: devuelve el marco de datos con posiciones de puntos mejoradas.

"Trazado" que generalmente es creado por packcircles: ya puede verlo funcionando aquí. mapa

  • compare este mapa 'después' con el fragmento de mapa 'antes' de la pregunta

0

¿Algo así, tal vez?

data$spacing_x = 5
data$spacing_y = 5

for(i in 2:nrow(data)) {
  if( abs(data$latitude[i]-data$latitude[i+1]) < 2 ) {
    data$spacing_y[i] = data$spacing_y + 6 +jitter(data$spacing_y,8)
    data$spacing_y[i+1] = data$spacing_y + 6 + jitter(data$spacing_y,8)
  }
}

for(i in 2:nrow(data)) {
     if( abs(data$longitude[i]-data$longitude[i+1]) < 2 ) {
      data$spacing_x[i] = data$spacing_x + jitter(data$spacing_x,4)
      data$spacing_x[i+1] = data$spacing_x +jitter(data$spacing_x,4)
     }
}

for(i in 2:nrow(data)) {
  if( abs(data$spacing_y[i]-data$spacing_y[i+1]) < 1.5 ) {
    data$spacing_y[i] = data$spacing_y + 2 
    data$spacing_y[i+1] = data$spacing_y + 2
  }
}

for(i in 2:nrow(data)) {
  if( abs(data$spacing_x[i]-data$spacing_x[i+1]) < 1.5 ) {
    data$spacing_x[i] = data$spacing_x + 2 
    data$spacing_x[i+1] = data$spacing_x + 2
  }
}


plot = autoplot(map) + 
  geom_segment(data = data
               , mapping=aes(x=longitude
                             , y=latitude
                             , xend=longitude + spacing_x
                             , yend=latitude + spacing_y)
               , size=0.5, color="black"
               , alpha = 0.9) +
  geom_point(data = data
             , aes(x = longitude+spacing_x
                  , y = latitude+spacing_y)
             , color = "white"
             , alpha = 0.8, size = 8) +
  geom_point(data = data
             , aes(x = longitude+spacing_x
                   , y = latitude+spacing_y
                   , color = sp_sum)
             , alpha = 0.3, size = 4)
  xlab("") +
  ylab("")
plot

Veo. Intentaste replicar las "líneas a la posición original" de la captura de pantalla de wals.info, ¿no? Es un comienzo, supongo. Pero si veo esto correctamente, no resolverá la mejor parte de mi problema (por ejemplo, los puntos aún se superponen).
maj

El resto debería ser manipulación de marcos de datos. Un si / bucle for puede gobernar espaciamiento - una declaración en el mismo también se puede decir que si el espaciado entre los puntos es menor que x, marcarán como tal y que el marcador se puede utilizar para concatenar los puntos

Espero que alguien, o usted, pueda arreglar mi feo para los bucles. Buena suerte.

@InNoam: De hecho, estoy abierto a pistas sobre cómo podría funcionar esta 'manipulación de marcos de datos'.
maj
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.