一、作业要求
读取PDO指数文件数据,绘制1854-2023年,1月(红色实线+marker)和7月(蓝色虚线+marker)的PDO指数,使用twinx,绘制双纵坐标图,需要有legend,调整字体大小,使其达到美观。
二、数据来源
1854年1月至2024年12月PDO指数数据文件,用于练习pandas库中的pandas.read_csv读取数据的指令。
PDO from ERSST V5 https://psl.noaa.gov/pdo/ Using EOF from 1920 to 2014 for N Pacific (see webpage) |
三、代码
1、准备
引入数据处理的numpy、pandas库以及绘图需要的matplotlib库,更多详细介绍与用法可查询官网。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
我们要绘制的图像如果需要中文标注(横纵坐标名字,所绘制的变量名),以及为负数据的负号,需要以下代码进行引入。
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
2、读取文件
filename = 'timeseries.pdo.ersstv5.csv' # 文件路径,当数据文件与代码文件位于一个文件夹时,文件路径可以省略
df = pd.read_csv(filename, sep=',', header=0)
print(df)
JanPDO = df[0: 2040: 12] # 读取每年1月份数据,Python的索引是从0开始的,df[0]即为第一个元素。
janpdo = np.array(JanPDO) # 将数据类型更改为ndarray即数组
JulPDO = df[6: 2046: 12] # 读取7月份数据
julpdo = np.array(JulPDO)
更进阶一点的做法可以通个datatime这个库来进行数据的切片选择,后面读取NetCDF文件(.nc结尾)时还会涉及。
3、绘图
# 绘图 #
fig, ax1 = plt.subplots(figsize=(20, 4)) # 设置图形窗口和绘图区域
x = np.arange(1854,2024) # 横坐标,年份用numpy库的arange生成,左闭右开,表明生成1854-2023年的数组
#ax1.axis('auto') # 调整坐标轴,参数 'scale','auto','square',选择'auto'即自动调整时,
# Matplotlib会自动为你设置合适的坐标轴界限,所以通常不需要显式调用。
# 折线图绘制,x横坐标,janpdo[:,1]为纵坐标,绘制连线变成折线图
ax1.plot(x, janpdo[:,1], marker='s', markevery=4, c='r', linewidth=2, markerfacecolor='w',
markeredgecolor='r', linestyle='-', label='1月',alpha=0.7)
# janpdo是一个二维数组,第一列是日期,0000-00-00,年月日,第二列才是是数据,前面提到Python中数组(列表,元组皆是)索引从0开始,
# ':'冒号表示从头索引到尾,这里是每一行都索引,但列只索引第2列(数据)
# marker,linewidth,linestyle等参数可以搜索了解。
ax1.set_xlabel('年份', fontsize=12) # 横坐标名,fontsize用以调节字号大小,下同。
ax1.set_ylabel('1月PDO指数', fontsize=12) # 纵坐标名
ax1.legend(loc='upper left',fontsize=14, edgecolor='black') # 标注(对折线的说明),位置在图像左上,还可用数字设置位置(详情可以搜索)
ax1.set_title('1854-2023年1月和7月PDO指数',fontsize=18) # 设置标题
ax1.set_ylim(-3,4) # 设置y方向显示范围为(-3,4),这个范围外不显示
ax_jul = ax1.twinx() # 设置共轴,为第二条折线的绘制设置画布(共轴条件下,两个画布重合,两条曲线在一个子图中,后面会有多个子图的情形)
ax_jul.plot(x, julpdo[:,1], marker='o', markevery=4, c='blue', linewidth=2, markerfacecolor='w',
markeredgecolor='blue', linestyle='--', label='7月',alpha=0.7) # 同一月份
#ax_jul.bar(x, julpdo[:,1],width=1,color='steelblue',edgecolor='navy',label='7月',alpha=0.6)
ax_jul.set_ylabel('7月PDO指数',fontsize=12)
ax_jul.legend(loc='upper right',fontsize=14)
#ax_jul.set_ylim(-3,4)
plt.xlim(1850, 2024) # 设置x方向上显示范围,同plt.ylim
# 风格化设置,也可以说是个性化设置,可以搜索查询详情
ax_jul.tick_params(right=True, direction='out',labelsize=11) # 右边的刻度都显示,且刻度向外。labelsize设置标签大小
ax1.spines['bottom'].set_linewidth(1.5)
ax1.spines['left'].set_linewidth(1.5)
ax1.spines['top'].set_linewidth(1.5)
ax_jul.spines['right'].set_linewidth(1.5)
ax1.grid(axis='both', ls='-') # axis = 'both','x','y' ,网格的设置。axis是设置x,y方向的网格线是否显示;ls是线型的设置。
plt.show() # 展示图像
4、结果展示