数据分析-可视化工具matplotlib
一、数据分析的流程
①提出问题:明确想干什么;
②准备数据:将数据取出,进行预处理,以获得我们需要的数据;
③分析数据:使用工具、模型对数据进行分析;
④获得结论;
⑤结论可视化:将结论以图的形式展现,使分析结果清晰明了、易懂;
二、对比常用统计图
(1)折线图
以折线(线条)的上升下降来表示统计数量的增减变化的统计图,特点是:能够显示数据的变化趋势,反映事物随某个变量(如时间)的变化情况。简单的折线图如下:(源自matplotlib官网)
(2)直方图
直方图又称质量分布图,是表示资料变化情况的重要工具。直方图由一系列高度不同的纵向条纹或者线段表示数据的分布情况,一般用横轴表示数据范围,用纵轴表示分布情况。例如用直方图表示某学校各个年龄段各有多少人。绘制直方图需要确定组数和组距,即将数据分为多少组,相邻两组之间的间隔是多少,比如绘制(年龄-人数)的直方图时,设置组距为5,即每一组的范围分别为(05岁)、(610岁)....组数=(max(x)-min(x))/组距。组距的选择十分重要,通常情况下,应该尽量选择合适的组距使组数为整数。
直方图也分为频数直方图和频率直方图,即纵轴分别表示该组的数量和频率。
特点:绘制连续性的数据,展示一组或者多组数据的分布情况。直方图示例如下:(来自matplotlib官网)
(3)条形图
条形图是用来显示各个不同的事物对于某一个共同属性的比较情况,例如已知2019年各个城市的GDP,那么用条形图可以很直观的展示各个城市的GDP情况以及他们的对比关系。
特点:绘制离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别。条形图示例如下:(来自matplotlib官网)
(4)散点图
散点图表示在回归分析中,数据点在直角坐标系的分布情况。绘制散点图时,用两组数据构成多个坐标点,考察坐标点的分布,判断两个变量之间是否存在某种关联或者总结坐标点的分布模式、分布情况。
特点:判断变量之间是否存在数量关联趋势,展示离群点(分布规律)散点图示例如下:(来自matplotlib官网)
三、matplotlib绘制常用统计图
(1)绘制折线图
案例一:
假设一天中每个两个小时的气温分别是:15,13,14.5,17,20,25,26,26,26,27,22,18,15;使matplotlib画出该图形。代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
# 数据在x轴的位置,是一个可迭代对象
x =range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
plt.plot(x, y)
plt.show()
运行之后结果如下图:
在上图中,我们通过对函数plt.plot()传入两个列表参数x, y,便可以绘制折线图,然后调用函数plt.show()将绘制结果显示出来。但是通过观察上图,发现还存在一下问题:
①图片大小不够
②图片没有描述信息
③x,y轴的刻度显示不明确(刻度间距不合适)
④线条样式可能不合适
针对上述问题,修改代码如下所示:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
# 设置图片大小,以及dpi
plt.figure(figsize=(10, 8), dpi=80)
# 设置字体显示为指定的文件(windows路径为:)适用于各种操作系统
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 数据在x轴的位置,是一个可迭代对象
x =range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
plt.plot(x, y)
# 设置x轴的刻度 可以传一个range(),也可以传一个列表, 列表元素为坐标轴各点的值
plt.xticks(x)
# plt.xticks(range(2, 25))
# 设置y轴的刻度
plt.yticks(range(min(y), max(y)+1))
# 设置x,y轴的标签以及图片标题
plt.xlabel("时间", fontproperties=my_font)
plt.ylabel("温度(℃)", fontproperties=my_font)
plt.title("一天中气温变化情况(每隔两小时)", fontproperties=my_font)
# 保存图片在绘制之后
# 可以保存为.svg这种矢量图格式,放大之后不会有锯齿
plt.savefig("./p1.png")
plt.show()
运行结果如下:
案例二:
如果列表a表示十点到十一点两个小时之间每一分钟气温的变化,绘图表示。
代码如下:
from matplotlib import pyplot as plt
from matplotlib import font_manager
import random
# 设置图片大小,以及dpi
plt.figure(figsize=(10, 8), dpi=80)
# 设置字体显示为指定的文件(windows路径为:)适用于各种操作系统my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
x = range(0, 120)
y = [random.randint(25, 30)for i in range(120)]
plt.plot(x, y)
# 调整x轴的刻度_x = list(x) # 只有列表才能取步长,所以进行强制转换_xtick_labels = ["10点{}分".format(i)for i in range(60)]
_xtick_labels += ["11点{}分".format(i)for i in range(60)]
plt.xticks(_x[::5], _xtick_labels[::5], rotation=45, fontproperties=my_font) # 取步长为5,旋转270度,rotation表示旋转的度数# 添加描述信息plt.xlabel("时间", fontproperties=my_font)
plt.ylabel("温度 单位(℃)", fontproperties=my_font)
plt.title("10点到12点每分钟的气温变化情况", fontproperties=my_font)
plt.show()
结果如下图:
案例三:
假设大家在30岁的时候,根据自己的实际情况统计出来了11岁到30岁每年交的男女朋友的数量如列表[1,0,1,1,3,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1] ,以及某位朋友的上述情况列表[0,2,3,5,2,1, 1,0,3,4,6,3,1,1,0,2,1,1,3,2]。请绘制出该数据的折线图,以便分析每年交男女朋友的数量走势。
代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
# 设置字体
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 设置图的大小
plt.figure(figsize=(14, 7), dpi=80)
x =range(11, 31)
y = [1, 0, 1, 1, 3, 4, 3, 2, 3, 4, 4, 5, 6, 5, 4, 3, 3, 1, 1, 1]
y1 = [0, 2, 3, 5, 2, 1, 1, 0, 3, 4, 6, 3, 1, 1, 0, 2, 1, 1, 3, 2]
plt.plot(x, y, label="自己", color="orange", linestyle=":")
plt.plot(x, y1, label="同桌", color="cyan", linestyle="--")
# 设置x轴显示信息
x_labels = ["{}岁".format(i)for i in range(11, 31)]
_x =list(x)
plt.xticks(_x, x_labels, fontproperties=my_font)
plt.yticks(range(min(y), max(y)+2))
# 绘制网格
plt.grid(alpha=0.5)# alpha 表示透明度
# 添加描述信息
plt.xlabel("年龄(岁)", fontproperties=my_font)
plt.ylabel("男(女)朋友数量(个)", fontproperties=my_font)
plt.title("11岁到30岁每年所处对象的数量走势图", fontproperties=my_font)
# 添加图例
# 调用此方法之后,程序会结合plt.plot()方法中的label参数显示出图例
# 此方法接收字体的参数为prop
plt.legend(prop=my_font)
plt.show()
结果如下:
plt.plot()方法的参数:
@ label: 用来在plt.legend()方法调用时设置图例
@ color: 设置线条颜色
@ linestyle: 设置线条风格
@ linewidth: 设置线条粗细
matplotlib折线图总结:
·绘制折线图(plt.plot()方法)
·设置图片大小和分辨率(plt.figure()方法)
·实现图片保存(plt.savefig()方法)
·设置xy轴的刻度和字符串(plt.xticks())
·解决刻度稀疏或者密集的问题(plt.xticks()方法)
·设置标题、xy轴的label(title,xlabel,ylabel)
·设置字体(font_manager类,结合fontproperties参数)
·添加图例(plt.plot(label=”xx”),plt.legend()方法)
(2)绘制散点图
案例:
假设你通过爬虫获取到了北京2016年3,10月份每天白天的最高气温(分别位于列表a,b)那么此时如何寻找出气温随时间变化的某种规律?
代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 设置图片大小,设置分辨率
plt.figure(figsize=(14, 9), dpi=80)
y_3 = [11, 17, 16, 11, 12, 11, 6, 6, 7, 8, 9, 12, 15, 14, 17, 18
,21, 16, 17, 20, 14, 15, 15, 15, 19, 21, 22, 22, 22, 23, 21]
y_10 = [26, 26, 28, 19, 21, 17, 16, 19, 18, 20, 20, 19, 22, 23, 17,
20, 21, 20, 22, 15, 11, 15, 5, 13, 17, 10, 11, 13, 12, 13, 6]
x_3 =range(1, 32)
x_10 =range(40, 71)
# 绘制
plt.scatter(x_3, y_3, label="三月")
plt.scatter(x_10, y_10, label="十月")
# 调整x轴刻度
_x =list(x_3) +list(x_10)
_xticks_labels = ["3月{}日".format(i)for i in x_3]
_xticks_labels += ["10月{}日".format(i)for i in x_10]
plt.xticks(_x[::3], _xticks_labels[::3], fontproperties=my_font, rotation=45, fontsize=12)
# 设置附加信息
plt.xlabel("时间", fontproperties=my_font, fontsize=14)
plt.ylabel("温度(℃)", fontproperties=my_font, fontsize=14)
plt.title("三月与十月的最高气温趋势图", fontproperties=my_font, fontsize=14)
# 添加图例
plt.legend(prop=my_font)
plt.show()
结果如下:
(3)绘制条形图
案例一:
假设你获取到了2017年内地电影票房前20的电影列表a和电影票房数据列表b,那么如何更加直观的展示该数据?
代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
a = ["战狼2", "速度与激情8", "功夫瑜伽", "西游伏妖篇", "变形金刚", "最后的骑士",
"摔跤吧爸爸", "加勒比海盗5:死无对证", "金刚:骷髅岛", "极限特工:终极回归",
"生化危机6:终章", "乘风破浪", "神偷奶爸3", "智取威虎山", "大闹天竺", "金刚狼3:殊死一战",
"蜘蛛侠:英雄归来", "悟空传", "银河护卫队", "情圣"]
b = [56.01, 26.94, 17.53, 16.49, 15.45, 12.96, 11.8, 11.61, 11.28, 11.12,
10.49, 10.3, 8.75, 7.55, 7.32, 6.99, 6.88, 6.86, 6.58, 6.32]
plt.figure(figsize=(15, 10), dpi=80)
# 竖着的条形图# plt.bar(range(len(a)), b)
# plt.xticks(range(len(a)), a, fontproperties=my_font, rotation=90)
# 横着的条形图# 某些情况下横着的条形图比竖着的好看plt.barh(range(len(a)), b, height=0.3)
# 设置附加信息plt.xlabel("票房 单位(亿)", fontproperties=my_font)
# y轴刻度信息plt.yticks(range(len(a)), a, fontproperties=my_font)
plt.grid(alpha=0.3)
plt.show()
结果如下:
案例二:
假设你知道了列表a中电影分别在2017-09-14(b_14),2017-09-15(b_15),2017-09-16三天的票房,为了展示列表中电影本身的票房以及同其他电影数据的对比情况,应该如何更加直观的呈现该数据?
代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
plt.figure(figsize=(14, 9), dpi=80)
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
a = ["星球崛起3", "敦刻尔克", "蜘蛛侠", "战狼2"]
b_16 = [15746, 312, 4497, 319]
b_15 = [12357, 156, 2045, 168]
b_14 = [2358, 399, 2358, 362]
x_14 =list(range(len(a)))
x_15 = [i +0.3 for i in x_14]
x_16 = [i +0.3*2 for i in x_14]
print(len(x_14))
plt.bar(x_14, b_14, width=0.3, label="2017-09-14")
plt.bar(x_15, b_15, width=0.3, label="2017-09-15")
plt.bar(x_16, b_16, width=0.3, label="2017-09-16")
# 设置x轴的刻度
plt.xticks(list(x_15), a, fontproperties=my_font, fontsize=12)
# 设置图例
plt.legend()
plt.show()
注意:为了使条形图不重叠,应当使每个条形的位置向右偏移一定距离,并且满足:
条形宽度*条形数量<1,比如上述代码中的x_14,x_15,x_16的设置。
结果如下:
(4)绘制直方图
直方图的应用场景:
·用户的年龄状态
·一段时间内用户点击次数的分布状态
·用户活跃时间的分布状态
案例一:
频数分布直方图,假设你获取了250部电影的时长列表a,希望统计出这些电影时长的分布状态(比如时长为100分钟到120分钟的电影的数量,出现的频率)等信息,你应该如何呈现这些数据?(ps: 由于数据量比较大,因此使用随机数模拟上述数据)
代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
import random
# 设置组距为5,设置组距的时候应该注意尽量使(max(a)-min(a))能够整除组距
dis =5
a = [random.randint(80, 150)for i in range(251)]
# 组数
num_bin = (max(a)-min(a))//dis
plt.hist(a, num_bin)# 参数normed=1表示画出的图形是频率分布直方图
# 设置x轴的刻度
plt.xticks(range(min(a), max(a)+dis, dis))
plt.grid()
plt.show()
注:在组数为正整数的情况下,图形能正确绘制,当实际组数为小数时(即(max(a)-min(a))/dis为小数),获得的图形会有一定的偏移(如图十四,组数实际为小数)。解决方法为调整组距,使组数为正整数。
结果为:
案例二:
在美国 2004的人口普查发现有124million的人在离家较远的地方工作。根据他们从家里到上班地点所需要的时间,通过抽样统计列出了下表的数据,这些数据能够绘制成直方图吗?
interval = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 60, 90] (表示各个区间)
width = [5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 30, 60] (表示区间宽度)
quantity = [836, 2737, 3723, 3926, 3596, 1438, 3273, 642, 824, 613, 215, 47] (各区间频数)
分析:由于数据以及被统计好了,因此不能直接使用直方图画图函数plt.hist(),该函数会在使用时分析一遍各个区间的频数。(但是理论上如果用随机数来模拟原始数据,应该可以用直方图画图函数来绘制出图形)。由于数据已经统计好,因此直接使用条形图,使条形图的线条宽度占满x轴的一个区间,即图形直观上是直方图。
代码如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
import random
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 只需要设置条形图的宽度为1即可
plt.figure(figsize=(12, 8), dpi=80)
interval = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 60, 90]
width = [5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 30, 60]
quantity = [836, 2737, 3723, 3926, 3596, 1438, 3273, 642, 824, 613, 215, 47]
plt.bar(range(12), quantity, width=1)
_x = [i -0.5 for iin range(13)]
_xlabels = interval + [150]
plt.xticks(_x, _xlabels)
plt.ylabel("人数", fontproperties=my_font, fontsize=12)
plt.xlabel("时间", fontproperties=my_font, fontsize=12)
plt.grid()
plt.show()
四、总结
matplotlib使用流程:
·明确问题
·选择图形的呈现形式
·准备数据
·绘图和图形完善
matplotlib更多图形样式:
百度echart(前端应用,使用js)。
plotly:可视化工具,兼容matplotlib和pandas。(需要付费)
<本文档记录个人学习matplotlib绘图工具过程的总结!若有不当之处欢迎指正! >