本节主要介绍一些基本的三维图形绘制方法。三维图形表现为立体形状,一般至少三组数据才能实现图形元素的表现,相对来讲,显示复杂度较高。
我们先来搭一个基本框架。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
plt.subplot(projection=’3d’)
plt.show()
这里的subplot函数就是设置当前绘图环境为三维,同时需要导入必要的Axes3D类型。
这个就是三维绘图坐标空间,右下角会及时显示当前鼠标位于的空间坐标,
拖拽还能实现自由三维旋转。
我们先从线性图开始,绘制由线段组成的三维折线。为了能介绍清楚,我们先从一个简单例子说明起:
x = (0, 0, 1, 4, 5)
y = (1, 1, 1, 1, 2)
z = (2, 0, 3, 4, 5)
plt.plot(x, y, z)
plt.show()
这些折线的关键在于点,因此需要我们给出这些点的三维坐标,我们可以定义三个轴的坐标值,分别保存为三个列表,然后设置到plot中即可。
从图中可以看到,每个列表都是一个维度的数据,列表的长度就是点的个数,相应的线的个数应该是点的个数减一。
我们仍然以这一章一直在使用的股票数据为例。这次我们首先按照年、月分组,并统计
import pandas as pd
frame = pd.read_csv('C:\\temp\\股票数据.csv', encoding='GBK')
frame = frame.set_index('日期')
frame.index = pd.to_datetime(frame.index)
results = frame[['收盘价']].groupby([frame.index.year, frame.index.month]).mean()
print(results.index.codes[0])
print(results.index.codes[1])
print(results['收盘价'])
这个分组过程并不复杂,关键是如何获取分组后两个分组条件列,这里我们使用了codes属性,为0的就是第一个分组条件,即年,以此类推,为1的就是第二个分组条件,即月。此时,分组数据本身的大小意义不是很大,因此此时都会自动换成了数字序列。
然后我们就以这三个数据列来表达三维信息,
plt.subplot(projection=’3d’)
plt.plot(results.index.codes[0], results.index.codes[1], results[‘收盘价’])
plt.show()
当然,目前的结果似乎没有很好的展示效果,
通过旋转调整,可以看出随着年度的不断推移,月份不断从1到12再到1,就会产生明显的折线,并且平均收盘价不断呈现下降趋势。
而且,在早期一年当中的大起大落想象非常明显,后期一年当中的起伏相对变低。这也体现了这种三维分析的特点,往往可以进行更多维度的多角度观察。
接下来我们看看三维散点图。一般而言,三维线性图意义往往不大,除非结合时序关系,否则点与点之间的连线无法说明实质的意义。相对而言,散点图就更为常见,只需绘制点即可。
首先我们先取得收盘价、换手率、成交笔数三个数据按照年月汇总的平均值:
results = frame.groupby([frame.index.year, frame.index.month]).agg(val1=(‘收盘价’, ‘mean’), val2=(‘换手率’, ‘mean’), val3=(‘成交笔数’, ‘mean’))
print(results)
然后还是调用scatter函数实现:
ax = plt.subplot(projection=’3d’)
ax.scatter(results[‘val1’], results[‘val2’], results[‘val3’])
plt.show()
请注意,这里不能使用plt的scatter函数,因为它是二维散点图,如果要三维,需要理由plt的subplot函数返回当前绘图环境后再调用scatter,这个可以支持。
在图中旋转图形可以看出,大部分换手率都集中于2前后,
而且随着收盘价的不断增长,更易于出现成交笔数变大的趋势。
柱状图也可以进行三维绘制。比如可以按照年份,将每年的各个月统计数据分别做成一张柱状图,多次依次绘制后,就会形成三维效果:
results = frame[[‘收盘价’]].groupby([frame.index.year, frame.index.month]).mean()
plt.bar(results.index.codes[1], results[‘收盘价’], zs=results.index.codes[0])
plt.show()
其中,前两个分别表示在其中一个二维平面上传统的柱状图,分别是横轴月份,纵轴收盘价,最后一个zs参数表示第三个维度,即年份。
效果虽然看的出来,但是颜色并不能很好的区分。
为此,可以根据月份或者年份、甚至收盘价来设置不同的颜色:
import matplotlib.cm as cm
plt.bar(results.index.codes[1], results[‘收盘价’], zs=results.index.codes[0],
color=cm.ScalarMappable().to_rgba(results.index.codes[0]))
plt.show()
这里使用年度作为区分颜色标准,
从中可以看出各个年份的不同数据情况,仍然不同年份升降趋势并不相同,但是总体随着年份而收盘价总体逐渐下降。
与此类似的还有一个3D版本的柱状图:
ax = plt.subplot(projection=’3d’)
ax.bar3d(x=results.index.codes[1], y=results.index.codes[0], z=0, dx=1, dy=1, dz=results[‘收盘价’], color=cm.ScalarMappable().to_rgba(results.index.codes[0]))
plt.show()
它是subplot函数返回类型的方法,参数设置略微复杂些,其中可以x、y、z分别是每个方柱的底部点的坐标,为了底部对齐,我们把z设置为0。后面的dx和dy分别表示每个方块的宽度和厚度,而高度则可以定义为收盘价等统计数据。
效果差不多,但是立体感更强。