2017-06-11 1 views
0

J'essaie de tracer des points sur une carte en utilisant matplotlib et Basemap, où les points représentent le lat/long pour des bâtiments spécifiques. Ma carte trace en effet les points, mais les met au mauvais endroit. Quand j'utilise les mêmes données et que je fais la même chose en utilisant Bokeh, au lieu de matplotlib et basemap, j'obtiens l'intrigue correcte.Tracer des points lat/longs en utilisant la carte de base

est ici le résultat CORRECT dans Bokeh: Bokeh Version

Et voici le résultat INCORRECT Carte de base: Basemap Version

J'ai vu la discussion ailleurs sur StackOverflow qui a suggéré que cela pourrait être lié au fait que plot() "déplace" la longitude en quelque sorte. J'ai essayé la suggestion à partir de là, qui devait inclure la ligne: lons, lats = m.shiftdata (long, lat) et ensuite utiliser les données décalées. Cela n'a eu aucun impact visible.

Mon code échantillon complet qui génère à la fois des parcelles à fond de carte et Bokeh est ici:

import matplotlib.pyplot as plt 
from mpl_toolkits.basemap import Basemap 
import pandas as pd 

from bokeh.plotting import figure, show 
from bokeh.sampledata.us_states import data as states 
from bokeh.models import ColumnDataSource, Range1d 

# read in data to use for plotted points 
buildingdf = pd.read_csv('buildingdata.csv') 
lat = buildingdf['latitude'].values 
long = buildingdf['longitude'].values 

# determine range to print based on min, max lat and long of the data 
margin = .2 # buffer to add to the range 
lat_min = min(lat) - margin 
lat_max = max(lat) + margin 
long_min = min(long) - margin 
long_max = max(long) + margin 

# create map using BASEMAP 
m = Basemap(llcrnrlon=long_min, 
      llcrnrlat=lat_min, 
      urcrnrlon=long_max, 
      urcrnrlat=lat_max, 
      lat_0=(lat_max - lat_min)/2, 
      lon_0=(long_max-long_min)/2, 
      projection='merc', 
      resolution = 'h', 
      area_thresh=10000., 
      ) 
m.drawcoastlines() 
m.drawcountries() 
m.drawstates() 
m.drawmapboundary(fill_color='#46bcec') 
m.fillcontinents(color = 'white',lake_color='#46bcec') 
# convert lat and long to map projection coordinates 
lons, lats = m(long, lat) 
# plot points as red dots 
m.scatter(lons, lats, marker = 'o', color='r') 
plt.show() 


# create map using Bokeh 
source = ColumnDataSource(data = dict(lat = lat,lon = long)) 
# get state boundaries 
state_lats = [states[code]["lats"] for code in states] 
state_longs = [states[code]["lons"] for code in states] 

p = figure(
      toolbar_location="left", 
      plot_width=1100, 
      plot_height=700, 
      ) 

# limit the view to the min and max of the building data 
p.y_range = Range1d(lat_min, lat_max) 
p.x_range = Range1d(long_min, long_max) 
p.xaxis.visible = False 
p.yaxis.visible = False 
p.xgrid.grid_line_color = None 
p.ygrid.grid_line_color = None 

p.patches(state_longs, state_lats, fill_alpha=0.0, 
     line_color="black", line_width=2, line_alpha=0.3) 

p.circle(x="lon", y="lat", source = source, size=4.5, 
     fill_color='red', 
     line_color='grey', 
     line_alpha=.25 
     ) 
show(p) 

Je n'ai pas assez de points de réputation pour publier un lien vers les données ou de l'inclure ici.

Répondre

3

Dans le tracé de la carte de base, les points de dispersion sont masqués derrière le fillcontinents. Suppression des deux lignes

#m.drawmapboundary(fill_color='#46bcec') 
#m.fillcontinents(color = 'white',lake_color='#46bcec') 

montrerait les points. Parce que cela pourrait être indésirable, la meilleure solution serait de placer la dispersion sur le reste de la carte en utilisant l'argument zorder.

m.scatter(lons, lats, marker = 'o', color='r', zorder=5) 

enter image description here

Voici le code complet (et je voudrais vous demander d'inclure ce genre de runnable exemple minimal avec des données codées en dur la prochaine fois que poser une question, car il permet d'économiser tout le monde beaucoup de travail inventant les données soi-même):

import matplotlib.pyplot as plt 
from mpl_toolkits.basemap import Basemap 
import pandas as pd 
import io 

u = u"""latitude,longitude 
42.357778,-71.059444 
39.952222,-75.163889 
25.787778,-80.224167 
30.267222, -97.763889""" 

# read in data to use for plotted points 
buildingdf = pd.read_csv(io.StringIO(u), delimiter=",") 
lat = buildingdf['latitude'].values 
lon = buildingdf['longitude'].values 

# determine range to print based on min, max lat and lon of the data 
margin = 2 # buffer to add to the range 
lat_min = min(lat) - margin 
lat_max = max(lat) + margin 
lon_min = min(lon) - margin 
lon_max = max(lon) + margin 

# create map using BASEMAP 
m = Basemap(llcrnrlon=lon_min, 
      llcrnrlat=lat_min, 
      urcrnrlon=lon_max, 
      urcrnrlat=lat_max, 
      lat_0=(lat_max - lat_min)/2, 
      lon_0=(lon_max-lon_min)/2, 
      projection='merc', 
      resolution = 'h', 
      area_thresh=10000., 
      ) 
m.drawcoastlines() 
m.drawcountries() 
m.drawstates() 
m.drawmapboundary(fill_color='#46bcec') 
m.fillcontinents(color = 'white',lake_color='#46bcec') 
# convert lat and lon to map projection coordinates 
lons, lats = m(lon, lat) 
# plot points as red dots 
m.scatter(lons, lats, marker = 'o', color='r', zorder=5) 
plt.show() 
+0

Merci! Et je suis désolé de ne pas avoir inclus les données (ou au moins certaines données). Je voulais attacher le csv avec toutes les données mais je n'étais pas autorisé à le faire. Je n'ai pas pensé à ajouter les points de données comme vous l'avez fait. – rsgny

+0

Pour la prochaine fois vous savez comment le faire. ;-) Rappelez-vous également que même si vous ne pouvez pas mettre un lien directement dans, vous pouvez toujours fournir une URL sous forme de texte et d'autres personnes peuvent ensuite modifier le message en conséquence. Enfin, si cela résout le problème, vous pouvez considérer [accepter] (https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) la réponse. – ImportanceOfBeingErnest