12 votos

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

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

    name            longitude   latitude    sp_sum
1   Armenian moderno 45          40          ambos
2   Armenian moderno 45          40          ambos
3   Armenian moderno 45          40          espacial
4   Dieri           138         -28.1667    ambos
5   Dieri           138         -28.1667    ambos
6   Finlandés       25.5577     64.7628     no espacial
7   Tártaro de Crimea   28.1418     43.8398     espacial
8   Ese Ejja        -67.515     -11.7268    no espacial
9   Makhuwa         38.8052     -14.8509    no espacial
...

Estoy usando el paquete R ggplot2 (es el que conozco mejor, así que estaría feliz de seguir usándolo, pero también acepto otras soluciones). Aquí hay un recorte de un intento anterior (código: ver abajo 1):

Recorte de intento anterior

Para cada punto, me gustaría que la posición (aproximada) - así como el valor - sigan siendo visibles. (Si hay varios puntos para un solo idioma, pueden combinarse.)

¿Existe alguna manera...

  • ... de mover los puntos a un lado lo suficiente para que no haya superposición (menos aleatoriamente que, por ejemplo, usando geom_jitter - hay mucha de ese tipo de esquivar en el paquete beeswarm, por ejemplo)?
  • ... y/o tener algún tipo de "línea" que apunte a la posición original de un punto si tuviera que moverse?
  • ... o combinar puntos cercanos de una manera que sigan siendo claros (probablemente hay una técnica efectiva que utiliza binning, es decir, stat_bin* o algo con un efecto similar)?
  • ... o crear un "gráfico interactivo" como los que se ven en sitios web que aún pueden incluirse en un pdf (también estoy pensando en las capacidades de paquetes como animation y shiny 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 forma de hacer que también mueva los puntos.

¡Siéntete libre de pedir aclaraciones!

Nota: Soy consciente de que ha habido varias preguntas sobre superposición, pero las que he consultado parecen tener un propósito diferente (es decir, estadístico) (no afirmo haber leído todo, así que estaré encantado de aceptar un enlace también, por supuesto). Intentaré enumerar las publicaciones que conozco y que podrían 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 de arriba.

library(OpenStreetMap)
library(ggplot2)

data <- read.csv(header = T, sep = ",", dec = ".", quote= "'",
text = "'','name','longitude','latitude','sp_sum'
'1','Armenian moderno',45,40,'ambos'
'2','Armenian moderno',45,40,'ambos'
'3','Armenian moderno',45,40,'espacial'
'4','Dieri',138,-28.1667,'ambos'
'5','Dieri',138,-28.1667,'ambos'
'6','Finlandés',25.5577,64.7628,'no espacial'
'7','Tártaro de Crimea',28.1418,43.8398,'espacial'
'8','Sochiapam Chinantec',-96.6079,17.7985,'no espacial'
'9','Ese Ejja',-67.515,-11.7268,'no espacial'
'10','Makhuwa',38.8052,-14.8509,'no espacial'
'11','Mualang',111.077,0.31083,'no espacial'
'12','Martuthunira',116.607,-20.9294,'no espacial'
'13','Evenki',108.626,53.85,'ambos'
'14','Afrikaans',30,-22,'ambos'
'15','Male (Etiopía)',36.9892,5.91975,'ambos'
'16','Manchú',126.557,47.3122,'ambos'
'17','Dime',36.3329,6.20951,'no espacial'
'18','Koorete',37.8679,5.80545,'no espacial'
'19','Wolaytta',37.7537,6.32668,'ambos'
'20','Dizin',35.5763,6.1405,'ambos'")

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

0 votos

¿Hay algo que pueda mejorar para hacer la pregunta más fácil de entender y responder? ¡Por favor avísame si tienes alguna idea!

1 votos

Esto no es una pregunta con la que tenga habilidades relevantes para ayudar, pero la he votado para que aparezca un poco más arriba en algunas listas. Si no recibes comentarios que te ayuden a mejorarla, te recomiendo revisarla/reevaluarla con frecuencia teniendo en cuenta los consejos ofrecidos en meta.gis.stackexchange.com/a/3353

0 votos

Estoy pensando que es posible que desees utilizar alguna funcionalidad de gráficos dirigidos por fuerzas. 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 agrupamiento por proximidad) y utilizar el centroide del grupo como ancla y permitir que sus miembros floten (y no trazar el centroide en sí mismo, simplemente usarlo para anclar los vértices conectados en su pequeño gráfico). Y por supuesto, si algún grupo tiene solo un miembro, entonces ese también debería estar anclado en su ubicación.

2voto

David L Puntos 135

Hasta ahora solo he encontrado una solución alternativa bastante decente: El paquete R packcircles puede haber sido diseñado para otro propósito, pero hace un buen trabajo alejando los puntos entre sí (ver también la correspondiente entrada de blog). Puede que no entienda todos los detalles internos de este paquete, pero afortunadamente, como verás, el archivo de ejemplo del sitio web se puede usar casi directamente, solo es necesario cambiar los nombres de las variables, la distancia entre círculos (o puntos, dependiendo de las funciones que uses) y los "límites" del gráfico (es decir, 180°).

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

mapa

  • por favor, compara este mapa 'después' con el fragmento de mapa 'antes' de la pregunta

0voto

jay Puntos 916

¿Algo así, quizás?

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

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X