我想在Basemap上绘制轨迹,并将国家标签(名称)显示为叠加层。
以下是当前代码及其生成的地图:
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()
这导致地图:
这是迁徙鸟类的轨迹图。虽然这是一张非常漂亮的地图(!),但我需要国家/地区名称标签,因此很容易确定这只鸟飞过的国家。
是否有直接添加国家/地区名称的方式?
答案 0 :(得分:6)
我的解决方案依赖于将来可能会或可能不会提供的外部数据文件。但是,类似的数据可以在其他地方找到,所以这不应该是一个太大的问题。
首先,打印国家/地区名称标签的代码:
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])
所有这一切都是从here下载国家/地区数据库,然后选择当前在地图上的国家/地区,并标记它们。
完整的代码:
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()
最后,结果:
显然,这并没有像人们希望的那样仔细标注,并且应该实施一些关于国家规模,名称长度和地图大小的启发式方法,以使其完美,但这是一个很好的起点。