美文网首页
matplotlib学习笔记

matplotlib学习笔记

作者: Atalantes | 来源:发表于2019-04-27 22:06 被阅读0次

    数据分析-可视化工具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绘图工具过程的总结!若有不当之处欢迎指正! >

    相关文章

      网友评论

          本文标题:matplotlib学习笔记

          本文链接:https://www.haomeiwen.com/subject/nhvlnqtx.html