2015-06-21 20 views
7

Chciałbym narysować trajektorię na mapie bazowej i mieć etykiety krajów (nazwy) pokazane jako nakładka.Etykiety krajów na mapie bazowej

Oto aktualny kod, a mapa produkuje:

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() 

Powoduje mapie: Migration

To jest mapa z toru o migracji ptaków. Chociaż jest to bardzo ładna mapa (!), Potrzebuję oznaczeń nazwami krajów, więc łatwo jest określić kraje, przez które przelatuje ptak.

Czy istnieje prosty sposób dodawania nazw krajów?

+2

Wow, ten ptak podróżuje dość daleko! Jeśli potrzebujesz nazw i współrzędnych kraju, zajrzyj na [to pytanie] (http://stackoverflow.com/questions/2702309/need-a-list-of-all-countries-in-the-world-with-a współrzędna długości i szerokości geograficznej). Aby narysować tekst na mapie, spójrz na przykład nanoszenia nacisku na [tę stronę] (http://matplotlib.org/basemap/users/examples.html), wydaje się, że możesz po prostu zrobić "plt.text" (x, y, tekst) '. –

+0

Dziękujemy! To było bardzo pomocne. Wkrótce opublikuję pełne rozwiązanie poniżej. –

Odpowiedz

6

Moje rozwiązanie opiera się na zewnętrznym pliku danych, który może ale nie musi być dostępny w przyszłości. Jednak podobne dane można znaleźć gdzie indziej, więc nie powinno to być zbyt dużym problemem.

Najpierw kod do drukowania etykiet country-name:

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]) 

Wszystko to nie jest pobranie z bazy danych kraju lokalizacji z here, a następnie wybrać kraje, które są obecnie na mapie, a następnie oznaczyć je .

Kompletny kod:

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() 

i wreszcie wynik:

labeld-map

Oczywiście to nie jest tak starannie oznakowane jak można mieć nadzieję, a niektóre heurystyki dotyczące wielkości kraju, należy wprowadzić długość nazwy i rozmiar mapy, aby była idealna, ale jest to dobry punkt wyjścia.