2015-06-21 5 views
7

Ich möchte eine Trajektorie auf einer Basemap zeichnen und Länderbezeichnungen (Namen) als Overlay anzeigen lassen.Länderetiketten auf Basemap

Hier ist der aktuelle Code und die Karte, um diese produziert:

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


path = "path\\to\\data" 

animal_data = pd.DataFrame.from_csv(path, header=None) 
animal_data.columns = ["date", "time", "gps_lat", "gps_long"] 

# data cleaning omitted for clarity 

params = { 
     'projection':'merc', 
     'lat_0':animal_data.gps_lat.mean(), 
     'lon_0':animal_data.gps_long.mean(), 
     'resolution':'h', 
     'area_thresh':0.1, 
     'llcrnrlon':animal_data.gps_long.min()-10, 
     'llcrnrlat':animal_data.gps_lat.min()-10, 
     'urcrnrlon':animal_data.gps_long.max()+10, 
     'urcrnrlat':animal_data.gps_lat.max()+10 
} 
map = Basemap(**params) 

map.drawcoastlines() 
map.drawcountries() 
map.fillcontinents(color = 'coral') 
map.drawmapboundary()   

x, y = map(animal_data.gps_long.values, animal_data.gps_lat.values) 

map.plot(x, y, 'b-', linewidth=1)  
plt.show() 

Dies führt in der Karte: Migration

Dies ist eine Karte der Flugbahn eines Zugvogel. Während dies eine sehr schöne Karte (!) Ist, brauche ich Länder-Namen-Etiketten, so dass es einfach ist, die Länder zu bestimmen, durch die der Vogel fliegt.

Gibt es eine unkomplizierte Möglichkeit, die Ländernamen hinzuzufügen?

+2

Wow, dieser Vogel ist ziemlich weit weg! Wenn Sie Namen und Koordinaten von Ländern benötigen, sehen Sie sich [diese Frage] an (http://stackoverflow.com/questions/2702309/need-a-list-of-all-countries-in-the-world-with-a -lange-und-Breite-Koordination). Um einen Text auf einer Karte zu zeichnen, werfen Sie einen Blick auf das Beispiel von Druck auf [diese Seite] (http://matplotlib.org/basemap/users/examples.html), es scheint, dass Sie einfach 'plt.text 'tun können (x, y, Text) '. –

+0

Danke! Das war sehr hilfreich. Ich werde bald die komplette Lösung unten veröffentlichen. –

Antwort

6

Meine Lösung basiert auf einer externen Datendatei, die in Zukunft möglicherweise nicht verfügbar ist. Ähnliche Daten können jedoch an anderer Stelle gefunden werden, so dass dies kein allzu großes Problem darstellen sollte.

Zunächst wird der Code zum Drucken der Land-Namensetiketten:

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

class MyBasemap(Basemap):  
    def printcountries(self, d=3, max_len=12): 
     data = pd.io.parsers.read_csv("http://opengeocode.org/cude/download.php?file=/home/fashions/public_html/opengeocode.org/download/cow.txt", 
             sep=";", skiprows=28) 
     data = data[(data.latitude > self.llcrnrlat+d) & (data.latitude < self.urcrnrlat-d) & (data.longitude > self.llcrnrlon+d) & (data.longitude < self.urcrnrlon-d)] 
     for ix, country in data.iterrows():        
       plt.text(*self(country.longitude, country.latitude), s=country.BGN_name[:max_len]) 

All dies tut, ist eine Land-Standort-Datenbank von here herunterladen, dann Länder auswählen, die derzeit auf der Karte ist, und beschriftete .

Der vollständige Code:

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

class MyBasemap(Basemap):  
    def printcountries(self, d=3, max_len=12): 
     data = pd.io.parsers.read_csv("http://opengeocode.org/cude/download.php?file=/home/fashions/public_html/opengeocode.org/download/cow.txt", 
             sep=";", skiprows=28) 
     data = data[(data.latitude > self.llcrnrlat+d) & (data.latitude < self.urcrnrlat-d) & (data.longitude > self.llcrnrlon+d) & (data.longitude < self.urcrnrlon-d)] 
     for ix, country in data.iterrows():        
       plt.text(*self(country.longitude, country.latitude), s=country.BGN_name[:max_len]) 


path = "path\\to\\data" 

animal_data = pd.DataFrame.from_csv(path, header=None) 
animal_data.columns = ["date", "time", "gps_lat", "gps_long"] 

params = { 
     'projection':'merc', 
     'lat_0':animal_data.gps_lat.mean(), 
     'lon_0':animal_data.gps_long.mean(), 
     'resolution':'h', 
     'area_thresh':0.1, 
     'llcrnrlon':animal_data.gps_long.min()-10, 
     'llcrnrlat':animal_data.gps_lat.min()-10, 
     'urcrnrlon':animal_data.gps_long.max()+10, 
     'urcrnrlat':animal_data.gps_lat.max()+10 
} 

plt.figure() 
map = MyBasemap(**params) 

map.drawcoastlines() 
map.fillcontinents(color = 'coral') 
map.drawmapboundary()   
map.drawcountries() 
map.printcountries() 

x, y = map(animal_data.gps_long.values, animal_data.gps_lat.values) 

map.plot(x, y, 'b-', linewidth=1)  
plt.show() 

und schließlich das Ergebnis:

labeld-map

Offensichtlich ist dies nicht so sorgfältig markiert, wie man hoffen könnte, und einige Heuristik in Bezug auf die Größe des Landes, Namenslänge und Kartengröße sollten implementiert werden, um dies perfekt zu machen, aber dies ist ein guter Ausgangspunkt.

Verwandte Themen