上一次通过一个简单例子学习了图形的基本绘制方法,这次我们通过农企(AMD)的数据来学习五种基本图形的绘制
工具准备
- AMD股票数据(Nov 21,2015 - Nov 21,2016),下载
- S&P500同期指数,下载
- AMD最近四个季度的财报
- S&P500 同时段(AMD)的指数
- Numpy
- Matplotlib
- Python3.x
(数据来源:Yahoo Finance)
首先我们引入工具
import numpy as np import matplotlib as plt
接着使用loadtxt导入文件,我们的文件看上去是这个样子的
......
numpy可以很快地将现有的csv类型的数据导入
1 | date,high,low=np.loadtxt('Nov21-1yr.csv',delimiter = ',',converters ={0:bytespdate2num('%Y-%m-%d')},skiprows =1,usecols=(0,2,3),unpack=True) |
- 导入文件名 Nov21-1yr.csv
- delimiter 分隔符为','
- converters 如果有日期需要使用bytespdate2num解析内容,0代表第一列
- skiprows =1 跳过第一行
- usecols(0,2,3) 使用1,3,4行,值得注意的是,如果我们只要获取一行,要用元组表示:usecols(x,)
- unpack 将提取的数据分别放在三个列表里
散点图
简介
用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。散点图将序列显示为一组点。值由点在图表中的位置表示。类别由图表中的不同标记表示。散点图通常用于比较跨类别的聚合数据。(百度百科)
使用scatter函数,array1(x轴),array2(y轴)为两组数据
1 | plt.scatter(array1,array2,[parameters,...]) |
实例
首先我们获得AMD最近一年的最高价格,最低价格,日期
1 | date,high,low=np.loadtxt('Nov21-1yr.csv',delimiter = ',',converters ={0:bytespdate2num('%Y-%m-%d')},skiprows =1,usecols=(0,2,3),unpack=True) |
获得每日的价格波动范围,通过numpy读取的数据拥有array的格式,可以对两个同样大小的列表直接进行加减
diff = high -low
接着我们使用scatter函数作散点图
1 | plt.scatter(date,diff,alpha = 0.4) |
这里的alpha是透明度。添加了透明度属性后,颜色会变淡,而重合的点的颜色会加深,使散点图更加直观
>>> plt.show()
折线图
简介
折线图是排列在工作表的列或行中的数据可以绘制到折线图中。折线图可以显示随时间(根据常用比例设置)而变化的连续数据,因此非常适用于显示在相等时间间隔下数据的趋势。在折线图中,类别数据沿水平轴均匀分布,所有值数据沿垂直轴均匀分布。(百度百科)
使用plot函数,array1(x轴),array2(y轴)为两组数据
1 | plt.plot(array1,array2,[parameters,...]) |
如果需要表示日期,使用plot_date
1 | plt.plot_date(date_array1,array2,[parameters,...]) |
实例1:AMD股票走势
我们这里使用农企一年的股票走势来举例,首先我们先获取收盘价和日期
1 | date,close=np.loadtxt('Nov21-1yr.csv',delimiter = ',',converters = {0:bytespdate2num('%Y-%m-%d')},skiprows =1,usecols=(0,4),unpack=True) |
接着我们用获得的数据来绘制折线图。正常情况下我们应该使用plot函数。但是由于我们涉及日期,为了更好地展现我们的图标。我们使用plot_date函数
1 | plt.plot_date(date,close,linestyle='-',markersize =2.5,color='#147FB1',label='AMD') |
- linestyle: 这里规定折线线段的种类。使用plot_date时,默认为圆点(类似散点图),所以我们使用'-'代表线段
- markersize:这是图中每一个圆点的大小,当markersize和线段粗细相同时无法显示
>>> plt.show()
实例2:S&P500走势
动手试试用同样的办法来绘制S&P500最近一年(Nov 21,2015 - Nov 21,2016)的走势
比较S&P500与AMD
如果我们直接进行S&P500和农企的比较,会发现农企是一条贴近X轴的线(AMD是个位数,S&P是4位数)。所以在我们需要将S&P500的值缩小比例,具体方法是先求出每日的变化率,然后使用同一起点(AMD第一天的收盘价),根据变化率来模拟走势
这里我们需要两个S&P500的变量:spopen,spclose;和两个之前AMD的变量close,date
首先我们求出每日的变化率,得到一年的变化率列表
1 2 | #(收盘价-开盘价)/开盘价 spchanges = np.divide(spclose-spopen,spopen) |
接着是一个缩小比例的函数,假设第一天的收盘价(指数)作为第二天的开盘价(指数),接收一个起点价格和从该点开始一年的变动
1 2 3 4 5 6 | def sp500_scale_down(start_point,changes): stdsp = [] for each in changes: start_point = start_point*(1+each) stdsp.append(start_point) return np.array(stdsp) |
看看我们如何调用这个函数
1 | stdsp = sp500_scale_down(close[-1]/(1+spchanges[-1]),spchanges[::-1]) |
这时我们获得了一个缩小版的S&P500指数列表stdsp。注意我们这个列表的内容都是从后往前的,即close[0]代表的是Nov 21,2016这一天而不是最靠前的Nov 21,2015.所以我们的第一天其实是列表的最后一个,即close[-1],spchanges同理。 而[::-1]表示反转列表,将其变回正常顺序。
绘制农企和S&P500的走势
1 2 | plt.plot_date(date,close,linestyle='-',markersize =2.5,color='#147FB1',label='AMD') plt.plot_date(date,stdsp[::-1],linestyle='-',markersize =2.5,color='#14B158',label='S&P500') |
为什么我们的stdsp要在这里反转呢?因为我们之前提到过我们提取的数据是从后往前的,可是,我们画出来的数据方向不是反的,这说明plot_date函数接收一个“反”着的列表,而我们的stdsp列表是从前往后推的,我们需要将其反转
绘制图例
1 | plt.legend(loc = 'upper left') |
>>> plt.show()
条形图
简介
排列在工作表的列或行中的数据可以绘制到条形图中。条形图显示各个项目之间的比较情况。(百度百科)
绘制条形图,我们需要bar函数(纵向)或barh函数(横向),x_array代表分布在x轴的点,y_array代表高度
1 | plt.bar(left=x_array,height=y_array,[parameters,...]) |
条形图实例:AMD4个季度营业额
首先我们获取农企最近四个季度的营业额,我们可以到AMD的官网,SEC里EDGAR的10Q或者其他第三方网站(Yahoo Finance)中找到
1 2 | #单位:'M(百万)' revenue = [958,832,1207,1307] |
接着生成四个条形图的位置列表
1 2 3 4 | #数量4个 N = 4 #生成x轴坐标列表[0,1.5,3.0,4.5] x = np.arange(N)*1.5 |
使用bar函数来绘制条形图
1 | plt.bar(left=x,height=revenue,color ='#51ADD8',width=0.5,align='center') |
- left 表示条形图在x轴的位置,以条形图左下角的点为坐标点
- width 表示条形图的宽度
- height 表示条形图高度
- align='center' 文字居中
接着使用日期来标记,分别是四个季度出财报(10-Q)的日期,并定位
1 2 3 | x_date=['12/26/2015','3/26/2016','6/25/2016','9/24/2016'] x_namepos =np.arange(4)*1.5 plt.xticks(x_namepos,x_date) |
>>> plt.show()
条形图(横向)实例
前面我们知道了一个标准的条形图该如何绘制,有的时候我们会想要使用横向的条形图该怎么办,和bar差不多,matplotlib在这里提供了barh函数
1 | plt.barh(left = 0,bottom=y,height=0.5,color ='#51ADD8',width=revenue,align='center') |
- bottom 表示条形图在y轴的位置,以条形图左上角的点为坐标点
- width 横过来表示长度
- height 竖过来表示宽度
>>> plt.show()
条形图对比实例
除了营业额,我们还可以来看一下两个条形图如何在一起对比,这里我们增加了农企的四个季度净利润
1 2 | #单位:'M(百万)' income = [-102,-109,69,-406] |
之前我们设定了两个营业额条形图间距为1.5,添加了净额之后我们预期的结构是这样的
1 2 3 4 | 0.5:营业额1 0.5:净额1 0.5:间距 0.5:营业额2 |
所以绘制净额
1 | plt.bar(left=x+0.5,height=income,color ='#51ADD8',width=0.5,alpha=0.75,align='center',label="Net Income") |
- left 在营业额的坐标点增加0.5(营业额width)
添加日期,图例
1 2 3 4 | plt.legend(loc = 'upper left') x_datepos =np.add(np.arange(4)*1.5,0.25) x_date=['12/26/2015','3/26/2016','6/25/2016','9/24/2016'] plt.xticks(x_datepos,x_date) |
>>> plt.show()
直方图
简介
直方图(Histogram)又称质量分布图。是一种统计报告图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据类型,纵轴表示分布情况。(百科词条)
绘制直方图我们使用hist函数,array表示变量集合,bins代表分布数量
1 | plt.hist(array,bins=20,[parameters,...]) |
实例:AMD股价变化率正态分布
获取股票价格
1 | open_price,close_price=np.loadtxt('Nov21-1yr.csv',delimiter = ',',skiprows =1,usecols=(1,4),unpack=True) |
获取变化率,使用百分比(乘以100)
1 | diff = ((close_price-open_price)/open_price)*100 |
绘制直方图,分30个连续的区间,并使用正态分布
1 | plt.hist(diff,bins=30,color='#EA4545',normed=True) |
>>> plt.show()
饼图
扇形统计图是用整个圆表示总数,用圆内各个扇形的大小表示各部分数量占总数的百分数。通过扇形统计图可以很清楚地表示出各部分数量同总数之间的关系。百分数.。 扇形统计图可以清楚地表示各个项目与总数之间的关系。(百科词条)
绘制饼图很简单,我们只需要使用pie函数和一组数据即可完成
1 | plt.pie(fracs,[parameters,...]) |
实例:AMD资产结构
我们先找到农企2016第三季度的财报(10-Q),可以从公司官网或者SEC(美国证监会)找到,如下图
找到资产下的子分类,作为标签
1 | labels = ['Cash','A/R','Inventories','GLOBF','Prepaid','Other Current','Property','Goodwill','Investments','Others'] |
对应的值为
1 | asset_items = [1258,640,772,13,63,78,161,289,60,282] |
如果是common size balance sheet的话,我们以资产总和为100%,每个自分类表示为对应的百分比
1 | fracs = [round(each/sum(asset_items)*100,1) for each in asset_items] |
绘制之前添加一组颜色,这组颜色对应每一个板块的颜色,可以自行选择
1 | colors =['#f26e6e','#6e7ef2','#6ed1f2','#f29d6e','#e1f26e','#b7f26e','#a46ef2','#f2ec6e','#6ef2a3','#51a0aa'] |
将比例设置为1,使最终效果为圆形
1 | plt.axes(aspect =1) |
绘制
1 | plt.pie(fracs,labels = labels,colors = colors,autopct = '%.1f') |
- labels 使用我们预设的标签
- color 使用我们预设的颜色
- autopct 将数字标记在上面
>>> plt.show()
哇咧!下面的字叠在一起了,没法看了。该怎么办呢?我们可以使用之前学过的箭头来指向特别窄的扇区,但是还有另一种更简单粗暴的办法。
转个角度
我们添加初始角度
1 | plt.pie(fracs,labels = labels,colors = colors,autopct = '%.1f',startangle=100) |
是不是好多了呢?