添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
使用python 绘制地图并在地图上绘制坐标点

使用python 绘制地图并在地图上绘制坐标点

2 年前 · 来自专栏 python绘图

使用python 绘制地图并在地图上绘制坐标点

1. 引言

本来想详细写一写Basemap的详细使用,但是看到了已经有人写得非常详细,如果想使用Basemap 的同学强烈推荐这篇文章

,本文就从挑选其中一方面详细介绍一下,并对其中未提到的一些细节补充一下。 ​ 本文将详细介绍如何使用Python (Basemap库函数)绘制一张美观的测站分布图(解决了plt.text()文字重叠的问题,以及标签的设置),先上最终结果图,分布图包含了测站的名称和接收机类型。首先上最终效果图:


关于Basemap的安装,教程很多不再赘述,自行百度,传送门傻瓜式教学: window下安装basemap 。关于Basemap的使用,必须再次推荐一下篇文章: 我用Python之basemap画图27问



2.绘制一张简单的地图

 from mpl_toolkits.basemap import Basemap  #导入Basemap库
 import matplotlib.pyplot as plt
 #import pandas as pd
 #styles = plt.style.available
 #plt.style.use(['science', 'high-vis', 'no-latex'])
 #绘制地图 加入站点
 plt.figure(figsize=(40, 30))  #它的参数figsize=(16,8)定义了图的大小。
 m = Basemap()  #使用Basemap()创建一个地图
 m.drawcoastlines()  #把海岸线画上
 m.drawcountries(color='grey', linewidth=2)  # 开始画上国家
 # 填充陆地、胡泊、海洋的颜色
 m.fillcontinents(
     color='g',  # 陆地颜色
     lake_color='b',  # 湖泊颜色
     alpha=0.2)
 #m.drawmapboundary(fill_color='blue')    # 填充海洋
 # 添加经纬线
 m.drawmeridians(
     np.arange(0, 360, 30),#设置纬线的其实范围,以及维度的间隔
     color='pink',  # 颜色
     linewidth=8,  # 线宽
     labels=[1, True, 0, True],
     fontsize=50,
 m.drawparallels(
     np.arange(-90, 90, 30),
     color='green',  # 颜色
     linewidth=8,  # 线宽
     labels=[1, True, 0, 1],
     fontsize=50,
 )


效果如如下:

3.测站坐标数据读取

 import pandas as pd
 from collections import OrderedDict
 from adjustText import adjust_text
 styles = plt.style.available
 plt.style.use(['science', 'high-vis', 'no-latex'])
 filepath = r'F:\MP Summary\B1IB2IB3I.csv'
 filepath




    
 = r'F:\MP Summary\B1CB2aB2b.csv'
 fpath = r'F:\Thesis\Results\GPS\endoutput\statistic.txt'
 #fpath = r'F:\Thesis\Results\TRIMBLE_GPS\endoutput\statistic.txt'
 data = pd.read_csv(filepath, )
 d = data.set_index(data['staname'])
 sta = list(d['staname'])
 rectype = list(d['RecType'])
 tp = list(d.drop_duplicates(subset=['RecType'], keep='first')['RecType'])
 stainfo = {sta[i]: rectype[i] for i in range(len(sta))}
 colors = [
     'blue', 'r', 'black', 'm', 'darkolivegreen', 'purple', 'dodgerblue',
     'brown'
 rec_color = {tp[i]: colors[i] for i in range(len(tp))}
 colormap = {sta[i]: rec_color[stainfo[sta[i]]] for i in range(len(sta))} #不同接收机类型映射不同的颜色
 StationPos = pd.read_table(fpath,
                            sep=r'\s+',
                            skiprows=0,
                            engine='python',
                            header=None)
 StationPos = pd.DataFrame(StationPos).loc[:, (0, 2, 3)].drop_duplicates()
 StationPos.columns = ['StaName', 'latitude', 'longitude']
 StationPos.index = range(0, len(StationPos.index))
 StationPos = StationPos.drop_duplicates(subset=['StaName'], keep='first')
 StationPos = StationPos[StationPos['StaName'].isin(sta)]
 #StationPos = StationPos.loc[0:(StaNum-1),:];
 #-----------需要绘制的站点的经纬度信息测站名称----------#
 lon = list(StationPos.longitude)
 #on = StationPos.longitude;
 lat = list(StationPos.latitude)
 #at = StationPos.latitude;
 staname = list(StationPos.StaName)
 print('lon:{}\n lat:{}\n staname:{}\n'.format(lon,lat,staname))
 lon:[149.0, 74.7, -52.8, 21.0, -4.4, 5.1, -4.0, -15.6, -104.0, -68.8,
 -69.4, 116.2, -46.0, -22.0, -120.9, 144.9, -76.8, 14.8, 141.8, -147.5, -156.3, 39.6, -66.6, 148.3, -149.6, -108.1, -114.5, 114.4, 12.9, 87.6, -65.4, 107.1, 6.4, -52.7, 55.5, -67.8, -67.8, 121.0, 13.1, 170.5, 11.9, 141.1, 24.4, 45.3, -57.9, -61.0, 12.4, 70.3, -52.6, 21.0, 114.5, 14.8, 127.9, -45.0, -4.5, -71.5, -149.6, 4.4, 66.9, -28.0, 20.3, 21.1, 120.2, 118.4]
      lat:[-35.3, 42.7, 5.3, 67.9, 40.5, 50.0, 40.4, 27.8, 30.7, 76.5, -35.8, -31.0, 60.7, 70.5, 40.0, 13.6, 39.0, 49.9, 43.5, 65.0, 20.7, -69.0, 46.0, -33.0, -17.6, 34.3, 62.5, 30.5, 49.1, 43.8, -24.7, 47.9, 51.0, 47.6, -4.7, -53.8, -53.8, 14.5, 52.4, -45.9, 78.9, 39.1, 60.2, -12.8, -34.9, 14.6, 51.4, -49.4, 5.1, 52.1, 30.5, 49.9, 35.6, -22.7, 48.4, -16.5, -17.6, 50.8, 39.1, 39.1, 49.0, 67.9, 23.0, 24.5]
      staname:['str2', 'pol2', 'kour', 'kiru', 'cebr', 'redu', 'vill', 'mas1', 'mgo5', 'thu2', 'mgue', 'nnor', 'qaq1', 'scor', 'quin', 'guam', 'godn', 'gop6', 'stk2', 'gcgo', 'mao0', 'syog', 'unb3', 'park', 'faa1', 'pie1', 'yel2', 'wuh2', 'wtzs', 'urum', 'unsa', 'ulab', 'tit2', 'stj3', 'seyg', 'rio2', 'rgdg', 'ptgg', 'pots', 'ous2', 'nya2', 'mizu', 'metg', 'mayg', 'lpgs', 'lmmf', 'leij', 'krgg', 'koug', 'joze', 'jfng', 'gope', 'gamg', 'chpg', 'brst', 'areg', 'thtg', 'brux', 'kit3', 'enao', 'ganp', 'kir8', 'cksv', 'kmnm'] ```
 

4.在地图上绘制点

 #----------在地图上绘制坐标点,添加文字------------#
 for i in range(len(staname)):
     m.scatter(lon[i],
               lat[i],
               s=150,
               c=colormap[staname[i]],
               marker='o',
               label=stainfo[staname[i]])
 #此处可以直接使用 m.scatter(lon,lat)
 #---------在坐标点添加文字------#
 plt.text(lon,       #坐标
          lat,
          staname,   #文字字符串
          fontsize=40,
          style="italic",
          weight="light",
          verticalalignment='center',
          horizontalalignment='right',
          rotation=0))  #给散点加标签

绘制的地图存在着两个问题:

  • legend标签重复
  • 文字重叠

5. adjustText解决plt.text()文字重叠的问题

文字重叠解决起来非常麻烦,但是谁让它遇到的是除了生小孩无所不能的python 呢。python为我们提供了一个库函数很好的解决了plt.text()文字重叠的问题。

关于这个库函数的更多使用细节请看: adjustText解决matplotlib plt.text()文字重叠问题

 from collections import OrderedDict
 from adjustText import adjust_text  #导入文字调整的库函数
 texts = []
 #plt.legend(loc ='best')
 for i in range(len(staname)):
     texts.append(
         plt.text(lon[i],
                  lat[i],
                  staname[i],
                  fontsize=40,
                  color=colormap[staname[i]],
                  style="italic",
                  weight="light",
                  verticalalignment='center',
                  horizontalalignment='right',
                  rotation=0))  #给散点加标签
 adjust_text(
     texts,
     only_move={'text': 'xy'},
     arrowprops=OrderedDict(arrowstyle='->', color='red'),
 plt.legend(loc ='best')
 #save_steps=True,save_prefix=savepath)

6.删除多余冗余的legend

我们看到图中有很多重复的图例可以使用以下方法删除

 plt.legend(loc ='best')
 #save_steps=True,save_prefix=savepath)
 #----------设置图片的标题---------------#
 plt.title(
     'Station(B1CB2aB2b) Distribution Map ',
     loc='center',
     fontsize=50,
     c='black',
     verticalalignment='top',
 #   bbox=dict(facecolor='g', edgecolor='b', alpha=0.65 )); #设置标题边框jk
 plt.tight_layout()
 #----------删除多余重复图例----------------------#
 handles, labels = plt.gca().get_legend_handles_labels()
 by_label = OrderedDict(zip(labels, handles))
 plt.legend(by_label.values(),
            by_label.keys(),
            loc='upper right',