在Matplotlib+Pandas:绘制温湿度对比图(1)中,绘制和优化了温湿度变化比较图,最终结果较为满意。发文后没过多久,有同学私聊我,给我发了一张图(如下所示),很洋洋得意的告诉我,他觉得两个子图太麻烦,试着试着用了一张图将我的前文可视化结果展示出来了。
我起初很欣喜,终于有学生会举一反三了,但是看着图,看着看着觉得不对劲了= =|||
乍一看,给人一种完美可视化结果的感觉,到底错在哪里呢?
上图,将温度与湿度用同一个坐标轴(纵轴)表示,默认了温度与湿度是同一个度量单位(量纲),犯了典型的常识错误!我们都知道温度单位是摄氏度,而湿度常用相对湿度表示,它没有单位,它是一个比值(百分比)。
因此,在绘制可视化结果时,应该用不同的坐标刻度表示,即图的左边和右边分别绘制相应属性的坐标刻度。
既然问题找到了,接下来进行“改错”。
Matplotlib中主次坐标轴画法
这句话读起来很高级,其实非常简单。直接上代码上图,进行直观学习
先上错误代码,分析错误原因,之后改正,加深映像
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
df = pd.read_excel('D:PycharmProjectsData exercises数据可视化数据.xlsx')
print(df)
x = df['时间']
y1 = df['温度']
y2 = df['湿度']
fig = plt.figure(figsize = (12,6))
plt.plot(x, y1)
plt.plot(x, y2)
plt.legend()
plt.xlabel('时间')
plt.ylabel('温度及湿度')
plt.title('温度湿度随时间变化走势图')
plt.xticks(rotation=-20)
plt.show()
在上述代码中,利用两次plt.plot()进行绘制操作,由于两次传入的值不同,因此,画出了两个曲线(温度、湿度),没问题,是正确的。
错误的地方在于没有分别设置X轴,Y轴,只基于Matplotlib中默认方式进行了展示。
解决办法:twinx()→作用是产生一个Y轴的镜面坐标系
例如,如下代码,将产生一个默认横纵坐标为[0, 1]的可视化界面
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = plt.subplot()
plt.show()
接下来,利用twinx()进行镜像操作,代码和可视化结果如下
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = plt.subplot()
ax2 = ax1.twinx()
plt.show()
ax2 = ax1.twinx()的意思是对ax1的坐标面进行镜像操作,产生一个镜像坐标面,该坐标面被保存在ax2中。
产生了想要的效果,接下来的操作就顺风顺水了(希望如此= =|||)
ax1.plot(x, y1, color='r')
ax2.plot(x, y2, color='b')
通过plot()可以向ax1和ax2坐标面给值,进行绘制,完整代码如下
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
df = pd.read_excel('D:PycharmProjectsData exercises数据可视化数据.xlsx')
x = df['时间']
y1 = df['温度']
y2 = df['湿度']
fig = plt.figure()
ax1 = plt.subplot()
ax2= ax1.twinx()
ax1.plot(x, y1, color='r')
ax2.plot(x, y2, color='b')
plt.show()
有些人一看图,怎么觉得和第七讲最后的图差别很大?原因是第七讲的图被预先缩放了画布比例。给上述代码中fig = plt.figure()给定和第七讲内容一样的画布大小(因为第七讲中是两个子图共用一块画布,所有在这里需要将宽再缩小一倍,即长、宽分别为13和2)
fig = plt.figure(figsize = (13,2))
修改后再次出图,如下图所示,几乎和第七讲中最后的图没有区别,只不过这里是在一张图中显示两个属性随时间的变化情况,而第七讲中的是分别划分两个子图进行显示
“洁癖”又犯了......上图实在太丑,我们继续优化。优化点还是两个:
第一,坐标轴标签以及刻度优化;第二,图例
(1)坐标轴标签标注以及刻度优化
对各个坐标轴进行标注,代码如下:
ax1.set_xlabel('时间')
ax1.set_ylabel('温度')
ax2.set_ylabel('湿度')
在这里,大家要记清楚一点!我们这个数据可视化图中共用X轴,那么X轴的标度是无法用前几课介绍的plt.xticks(rotation=-20)进行逆时针旋转二十度操作!
但是,网上有大神,秀了一波操作,可以用如下代码代替plt.xticks()进行共轴坐标轴的旋转,代码如下:
for xtick in ax1.get_xticklabels():
xtick.set_rotation(-20)
非常的秀,由此可见,代码是非常灵活的!
坐标轴标签标注以及刻度优化代码如下:
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
df = pd.read_excel('D:PycharmProjectsData exercises数据可视化数据.xlsx')
x = df['时间']
y1 = df['温度']
y2 = df['湿度']
fig = plt.figure(figsize = (12,6))
ax1 = plt.subplot()
ax2= ax1.twinx()
ax1.plot(x, y1, color='r')
ax2.plot(x, y2, color='b')
ax1.set_xlabel('时间')
ax1.set_ylabel('温度')
ax2.set_ylabel('湿度')
for xtick in ax1.get_xticklabels():
xtick.set_rotation(-20)
plt.show()
(2)图例
这里我遇到一个坑,对于两个坐标平面,我连续用了两个legend()去做,但是每次只显示一个图例,刚开始以为是前一个图例覆盖了后一个图例,其实不然......原因是两个图例在默认情况下显示在了同一个位置,感官上是一个把一个掩盖了。折腾了半天,终于找到了解决办法,legend()的其中一个参数loc是给定图例在整个图上
例如legend(loc = 2)指定图例在图中的右上角显示,loc参数中一共是1~10,对应图中位置如下图所示:
添加图例后的代码及可视化结果如下所示:
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
df = pd.read_excel('D:PycharmProjectsData exercises数据可视化数据.xlsx')
x = df['时间']
y1 = df['温度']
y2 = df['湿度']
fig = plt.figure(figsize = (12,6))
ax1 = plt.subplot()
ax2= ax1.twinx()
ax1.plot(x, y1, color='r')
ax2.plot(x, y2, color='b')
ax1.set_xlabel('时间')
ax1.set_ylabel('温度')
ax2.set_ylabel('湿度')
for xtick in ax1.get_xticklabels():
xtick.set_rotation(-20)
plt.show()
作为一个追求完美的老师,上图中,图例是分散的,不符合我们的审美概念和习惯,图例应该是在一起显示,但是作为双Y轴图表,不能直接粗暴的使用
ax1.legend()
ax2.legend()
之前已经提到过,这样会发生覆盖现象
只能进行如下操作:
fig.legend(loc=1, bbox_to_anchor=(1,1), bbox_transform=ax1.transAxes)
这里给大家留个自学机会,去查阅legend()的参数及其作用
最终版,基于双Y轴可视化显示,代码及可视化结果如下(额外补充了图的标题)
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
df = pd.read_excel('D:PycharmProjectsData exercises数据可视化数据.xlsx')
x = df['时间']
y1 = df['温度']
y2 = df['湿度']
fig = plt.figure(figsize = (12,6))
ax1 = plt.subplot()
ax2 = ax1.twinx()
ax1.plot(x, y1, color='r')
ax2.plot(x, y2, color='b')
ax1.set_xlabel('时间')
ax1.set_ylabel('温度')
ax2.set_ylabel('湿度')
for xtick in ax1.get_xticklabels():
xtick.set_rotation(-20)
fig.legend(loc=1, bbox_to_anchor=(1,1), bbox_transform=ax1.transAxes)
plt.show()
越往后,坑越多,坑越多,学习的东西越多。需要消化的时间也越多~今天到此为止,喜欢的朋友们记得帮忙收藏点赞哦,谢谢~