使用python Basemap测站分布图(含站名)

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

1. 引言

​ 本来想详细写一写Basemap的详细使用,但是看到了已经有人写得非常详细,如果想使用Basemap 的同学强烈推荐这篇文章我用Python之basemap画图27问 ,本文就从挑选其中一方面详细介绍一下,并对其中未提到的一些细节补充一下。

​ 本文将详细介绍如何使用Python (Basemap库函数)绘制一张美观的测站分布图(解决了plt.text()文字重叠的问题,以及标签的设置),先上最终结果图,分布图包含了测站的名称和接收机类型。首先上最终效果图:

png

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

image-20210324192152819

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.rcParams['font.family'] = 'Arial'  # 设置字体样式
plt.rcParams['font.weight'] = 'bold'	#加粗
#绘制地图 加入站点
plt.figure(figsize=(40, 30))  #它的参数figsize=(16,8)定义了图的大小。
m = Basemap()  #使用Basemap()创建一个地图
# 限定地图的范围
"""m = Basemap(llcrnrlon= lons[0],
            llcrnrlat=lats[0],
            urcrnrlon=lons[1],
            urcrnrlat=lats[1],
            projection='merc',
            lat_1=33,
            lat_2=45,
            lon_0=100)  #使用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,
)

效果如如下:


png

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))  #给散点加标签


png

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

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


png

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',
           fontsize='xx-large')

# plt.savefig(savepath + 'Station_Distribution_Map_B1C2.svg',#保存图片
#             bbox_inches='tight',
#             dpi=600)  #dpi = 300);       #保存站点图
plt.show()  #显示这个地图

最后我们就能够得到一张测站分布图啦
png

  • 6
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值