Sobreposição de pontos em mapas em R (por exemplo, com ggplot2) - como empurrar pontos para o lado, marcar posições originais, combinar pontos próximos ...?


12

Eu tenho um banco de dados contendo idiomas, suas longitudes e latitudes e um valor de recurso (categoria 1, categoria 2 ou ambos - no gráfico, eles são marcados em vermelho, azul e verde, respectivamente). Pode haver até três pontos por idioma e, naturalmente, dois pontos de idioma podem estar muito próximos um do outro.

    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
...

Estou usando o pacote R ggplot2 (esse é o que eu estou mais familiarizado, por isso ficaria feliz em continuar usando - mas outras soluções também são bem-vindas). Aqui está um recorte de uma tentativa anterior (código: veja abaixo 1 ):

Cortar da tentativa anterior

Para cada ponto, eu gostaria que a posição (aproximada) - assim como o valor - ainda estivesse visível. (Se houver vários pontos em um único idioma, eles podem ser combinados.)

Existe uma maneira também ...

  • ... para mover pontos para o lado apenas o suficiente para que não haja overplotting (menos aleatoriamente do que, digamos, usando geom_jitter - há um monte de que tipo de desviando na beeswarm pacote por exemplo)?
  • ... e / ou ter algum tipo de "linha" apontando para a posição original de um ponto, caso ele precise ser movido?
  • ... ou combinar pontos próximos de uma maneira que eles ainda sejam claros (provavelmente existe uma técnica de trabalho por aí que usa binning, ou seja, stat_bin * ou algo com efeito semelhante)?
  • ... ou criar um "enredo interativo" como os vistos em sites que ainda podem ser incluídos em um pdf (estou pensando também nas habilidades de pacotes como animação e brilho aqui)? Por exemplo, fica assim em wals.info :

    Wals

Em uma postagem anterior aqui, eu sei que o pacote directlabels pode mover rótulos, mas não encontrei uma maneira de fazê-lo mover os pontos também.

Sinta-se livre para pedir esclarecimentos!

Observação: estou ciente de que houve várias perguntas sobre a plotagem, mas as que eu examinei parecem ter um propósito diferente (ou seja, estatístico) (não pretendo ter lido tudo , por isso ' ficaria feliz em aceitar um link também, é claro). Tentarei listar as postagens que eu conheço e que podem muito bem ser relevantes (- pelo que li, nenhuma delas responde exatamente à minha pergunta).


1 As seguintes linhas de código criaram o corte a partir de cima.

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

Existe algo que eu possa melhorar para facilitar a compreensão e a resposta da pergunta? Por favor deixe-me saber se você tem algumas ideas!
maj

1
Esta não é uma questão com a qual eu tenha habilidades relevantes para ajudar, mas eu a votei para fazê-la parecer um pouco mais alta em algumas listas. Se você não receber nenhum comentário que ajude a melhorá-lo e, em qualquer caso, recomendo revisá-lo / revisá-lo em intervalos frequentes, atendendo aos conselhos oferecidos em meta.gis.stackexchange.com/a/3353
PolyGeo

Eu estou pensando que você pode querer usar alguma funcionalidade de gráfico direcionado à força. Não tenho certeza de como fazê-lo e manter alguns pontos ancorados, mas o que estou pensando é identificar todos os clusters (por alguma função de agrupamento de proximidade) e usar o centróide do cluster como uma âncora e deixar seus membros flutuarem (e não plotando o próprio centróide - apenas usando-o para ancorar os vértices conectados em seu pequeno gráfico). E, claro, se algum cluster tiver apenas um membro, esses também deverão ser ancorados em sua localização.
aaryno

Não segui o lado em "... novamente parece se aplicar apenas a gráficos de dispersão", porque esse é um gráfico de dispersão.
whuber

Admito que devo ter usado um termo errado - o que eu quis dizer com gráfico de dispersão era o gráfico de dispersão estatístico típico em que a posição geralmente é menos importante do que no tipo de gráfico que temos aqui (= um mapa - se os pontos são movidos para cá, é óbvio imediatamente).
maj

Respostas:


2

Até agora, encontrei apenas uma solução alternativa bastante decente: o pacote packcircles R pode ter sido projetado para outra finalidade, mas faz um bom trabalho afastando os pontos um do outro (veja também a postagem do blog correspondente ). Talvez eu não entenda todo o funcionamento interno deste pacote, mas felizmente, como você encontrará, o arquivo de exemplo do site pode ser usado quase diretamente - tudo o que é necessário mudar é o nome da variável, a distância entre os círculos (ou pontos). , dependendo das funções utilizadas) e dos "limites" do gráfico (ou seja, 180 °).

(No final, tudo se resume à circleLayout()função, que utiliza um quadro de dados com colunas lon, lat e raio (ou seja, distância) e dois vetores xlim / ylim 2-numéricos - retorna o quadro de dados com posições de pontos aprimoradas.)

"Plot" que geralmente é criado por packcircles - você pode vê-lo funcionando aqui. mapa

  • compare esse mapa 'after' com o snippet de mapa 'before' da pergunta

0

Algo assim, talvez?

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

Entendo. Você tentou replicar as "linhas para a posição original" da captura de tela do wals.info, não tentou? É um começo, eu acho. Mas se eu ver isso corretamente, não resolverá a melhor parte do meu problema (por exemplo, os pontos ainda se sobrepõem).
maj

O restante deve ser manipulação de quadro de dados. Um if / loop pode governar espaçamento - uma declaração nela também pode dizer que se o espaçamento entre dois pontos é menor do que x, marcá-los como tal e que marcador pode ser usado para concatenar os pontos

espero que alguém, ou você, possa consertar meu feio por loops. Boa sorte.

@InNoam: Na verdade, estou aberto a sugestões de como essa 'manipulação de quadro de dados' poderia funcionar.
maj
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.