Matplotlib常用图表

Matplotlib绘图一般用于数据可视化

常用的图表有:

  1. 折线图
  2. 散点图 / 气泡图
  3. 条形图 / 柱状图
  4. 饼图
  5. 直方图
  6. 箱线图
  7. 热力图

需要知道的不只是如何绘图,更要知道什么样的数据用什么图表展示效果更好

import matplotlib.pyplot as plt

折线图

折线图用于显示随时间或有序类别的变化趋势

x = [1, 2, 3, 4, 5, 6]  # x轴坐标
y = [3, 5, 1, 8, 4, 9]  # y轴坐标

plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x5366f60>]

# 简写 :只写一个轴坐标,默认y轴(x轴自增)
plt.plot([2, 5, 1, 8, 4])
[<matplotlib.lines.Line2D at 0x5407358>]

线条和标记节点样式

标记字符:标记线条中的点

线条颜色:color='g'
线条风格:linestyle='--'
线条粗细:linewidth=5.0
标记风格:marker='o'
标记颜色:markerfacecolor='b'
标记尺寸:markersize=20
透明度:alpha=0.5

线条和标记节点格式字符

  • 如果不设置颜色,系统默认会取一个不同颜色来区别线条
  • 图像打印室,黑白打印机不能区分颜色,需要风格区分

颜色字符 风格字符 标记字符1 标记字符2
r红色 -实线 o实心圈标记 1下花三角标记
g绿色 --虚线 .点标记 2上花三角标记
b蓝色 -.点划线 ,像素标记 3左花三角标记
w白色 :点虚线 v倒三角标记 4右花三角标记
  | `''`留空 | `^`上三角标记 | `s`实心方形标记

c青色 | | >右三角标记 | p实心五角标记
m洋红 | | <左三角标记 | h竖六边形标记
y黄色 | | *星形标记 | H横六边形标记
k黑色 | | +十字标记 | D菱形标记
| | xX标记 | d瘦菱形标记
#00ff0016进制 | | ```垂直标记
0.8灰度值字符串 | |

plt.plot(
    [1,2,3,4,5,6],  # x轴坐标
    [3,5,1,8,4,9],  # y轴坐标
    
    # 线条样式
#     color='red',
#     color='r',
#     color='#000000', # 线条颜色
    linestyle='-',  # 线条样式
    linewidth=20,  # 线条粗细
    
    # 标记样式
    marker='p',  # 标记样式
    markerfacecolor='r',  # 标记颜色
    markersize=50,  # 标记大小
    alpha=0.5,  # 透明度
)
[<matplotlib.lines.Line2D at 0xc2ad4e0>]

案例:绘制2017年7月国际外汇市场美元 / 人民币汇率走势图

时间  收盘价
2017年7月3日   6.8007
2017年7月4日   6.8007
2017年7月5日   6.8015
2017年7月6日   6.8015
2017年7月7日   6.8060
2017年7月10日  6.8036
2017年7月11日  6.8025
2017年7月12日  6.7877
2017年7月13日  6.7835
2017年7月14日  6.7758
2017年7月17日  6.7700
2017年7月18日  6.7463
2017年7月19日  6.7519
2017年7月20日  6.7595
2017年7月21日  6.7669
2017年7月24日  6.7511
2017年7月25日  6.7511
2017年7月26日  6.7539
2017年7月27日  6.7430
2017年7月28日  6.7374
2017年7月31日  6.7265
# 汇率
eurcny = [6.8007,6.8007,6.8015,6.8015,6.8060,6.8036,6.8025,6.7877,6.7835,6.7758,6.7700,6.7463,6.7519,6.7595,6.7669,6.7511,6.7511,6.7539,6.7430,6.7374,6.7265]

# 日期
date = [3,4,5,6,7,10,11,12,13,14,17,18,19,20,21,24,25,26,27,28,31]

# 设置图像大小
plt.figure(figsize=(18, 8))

# 折线图
plt.plot(
    date,
    eurcny,
    
    color='y',
    linestyle='--',
    linewidth=10,
    
    marker='o',
    markersize=30,
    markerfacecolor='g',
    alpha=0.5,
)
# 第二条折线
plt.plot(eurcny)

# 网格
plt.grid(linewidth=0.2, alpha=0.5)


散点图 / 气泡图

散点图作用:

  • 单组数据,可以查看数据分布(不常用,最好使用直方图实现)
  • 多组数据,可以查看各数据之间是否存在相关性

坐标系中,每个值只用一个点(x轴,y轴确定)表示

x = [1,3,5,7,9,11,13,15,17]
y = [2,-5,19,3,5,8,12,6,1]

plt.scatter(x, y)
<matplotlib.collections.PathCollection at 0xb132828>

plt.scatter(
    [1,3,5,7,9,11,13,15,17],
    [2,-5,19,3,5,8,12,6,11],
    
    color='r',
    marker='o',
    linewidth=1,
    alpha=0.5,
    
    # 点大小
#     s=1000
    s=[50,100,150,200,250,300,350,400,450],
    
)

# 第二组散点图
plt.scatter(
    [10,12,16,18],
    [5,10,12,15],
)
<matplotlib.collections.PathCollection at 0xa9ce438>

案例:数据分析居民年龄 / 收入和超市销售额的对应关系

背景介绍

数据:

  • 顾客年龄
  • 顾客年收入
  • 顾客年购物金额

需求:

  • 分析出超市销售额和居民年龄、收入的关系
  • 解释关系产生的原因
  • 提出建议方案

数据

年龄  收入  销售额
34  350 123
40  450 114
37  169 135
30  189 139
44  183 117
36  80  121
32  166 133
26  120 140
32  75  133
36  40  133

2.指标计算步骤,略

3.数据可视化

用户年龄和销售额的关系

# 年龄
age = [34,40,37,30,44,36,32,26,32,36]
# 收入
income = [350,450,169,189,183,80,166,120,75,40]
# 销售额
sales = [123,114,135,139,117,121,133,140,133,133]

plt.scatter(age, sales)
<matplotlib.collections.PathCollection at 0xa280438>

用户收入和销售额的关系

plt.scatter(income, sales)
<matplotlib.collections.PathCollection at 0xa7763c8>

将三个维度数据画入一个图表

plt.scatter(![](https://img2018.cnblogs.com/blog/1480412/201812/1480412-20181212162151322-199498601.png)

    age,
    sales,
    # 点的大小:工资越高点越大
    s=income,
    alpha=0.5
)
<matplotlib.collections.PathCollection at 0xa3abf28>

4.结论:

  • 随着用户年龄的增加,销售额逐渐降低
  • 随着用户收入的增加,销售额也在降低

原因:

  • 老年人的消费水平不高,只买偏移商品
  • 高收入用户群体较少在本超市消费
  • 本超市的主流用户群体,是发展中的年轻人,销售商品偏年轻化贫民化

意见建议:

针对超市宣传推广营销活动的建议:

  • 营销对特定用户群体
    • 年龄25-37岁之间
    • 年收入20万以下
  • 应针对上述发展中的年轻人进行宣传推广活动

条形图 / 柱状图

  • 条形图(横向)
  • 柱状图(纵向)

条形图和柱状图用来比较各独立类别下的单独数据的大小

柱状图

x = [1,2,3,4,5]
y = [3,6,1,8,2]

plt.bar(x, y)
<BarContainer object of 5 artists>

plt.bar(
    x,
    y,
    
    width=0.3,  # 柱子粗细
    
    color='r',
    alpha=0.3
)

# 坐标纸和坐标标注 自定义
plt.xticks([1,2,3,4,5], ['a','b','c','d','e'])
plt.yticks([3,6,1,8,2], ['A','B','C','D','E'])

# 直接显示图像,其他编辑器绘图最后必须写这行代码否则没有图
plt.show()

条形图

  • 条形图粗细属性:height
  • 条形图的x、y坐标翻转
plt.barh(x, y, height=0.5)
<BarContainer object of 5 artists>

案例:某班级男生和女生各科成绩平均分数据可视化

学科	男生	女生
语文	85.5	94
数学	91	82
英语	72	89.5
物理	59	62
化学	66	49
# 男生平均分,语文 / 数学 / 英语 / 物理 / 化学
boy = [85.5,91,72,59,66]
# 女生平均分
girl = [94,82,89.5,62,49]

# 男生成绩

# x轴,各个学科
course = [1,2,3,4,5]

plt.bar(
    course,
    boy,
    width=0.3,
    color='g',
    alpha=0.3,
)

# 女生成绩
course2 = [1.3, 2.3, 3.3, 4.3, 5.3]

plt.bar(
    course2,
    girl,
    width=0.3,
    color='r',
    alpha=0.3
)

# 坐标轴和坐标轴标注
plt.xticks([1.15, 2.15, 3.15, 4.15, 5.15], ['Chi','Math','End','Phy','Che'])

# 将数据标注在柱子上
# plt.text(3, 50, 'abcde')

for i,j in zip(course,boy):
    plt.text(
        i,  # x轴,course学科位置
        j,  # y轴,boy分数
        '%.1f' % j,  # 数据转为一位小数
        ha='center',  # 水平对齐
        va='bottom',  # 垂直对齐
        alpha=0.5,
    )

for i,j in zip(course2,girl):
    plt.text(
        i,  # x轴,course学科位置
        j,  # y轴,boy分数
        '%.1f' % j,  # 数据转为一位小数
        ha='center',  # 水平对齐
        va='bottom',  # 垂直对齐
        alpha=0.5,
    )

plt.grid(linewidth=0.1)
plt.show()

饼图

饼图用于显示各项相对综合的百分比大小

# 数据会被饼图自动转化为百分比
p = [12,30,45,10]

plt.pie(p)
plt.show()

案例:2017年9国军费占比数据可视化

国家  军费占比
美国  0.5548467
中国  0.14444868
印度  0.05094268
沙特  0.04846696
俄国  0.046753
日本  0.04418206
英国  0.04161112
德国  0.03799276
法国  0.03075605
# 国家名
mark = ['America','China','India','Saudi','Russia','Japan','Britain','Germany','France']
# 各国占9国总军费的比例
percent = [0.5548467,0.14444868,0.05094268,0.04846696,0.046753,0.04418206,0.04161112,0.03799276,0.03075605]

plt.figure(figsize=(8, 8))

plt.pie(
    percent,  # 百分比
    labels=mark,  # 名称
    explode=(0, 0.1, 0, 0, 0, 0, 0, 0, 0), # 突出块,突出比例
    autopct='%1.1f%%',  # 显示百分比方式
    startangle=-100,  # 饼图起始的角度,度数,默认为0为右侧水平180度开始,逆时针旋转
)

plt.axis('equal')  # 正圆形饼图, x/y轴尺寸相等,默认是扁图
plt.show()

直方图

直方图是表达数据的分布情况的统计图表,一般用来表示同等区间内,某类数值出现的个数或频率(频率=出现次数/总数)

x轴表示分组数据,y轴表示分布情况

从频率分布直方图可以直观估计出:

  • 众数:频率分布直方图中最高举行的底边中点的横坐标
  • 中位数:把频率分布直方图分成两个面积相等部分的平行于Y轴的直线横坐标

直方图与柱状图的区别:

  • 直方图:分区之间连续无间断,表示连续变量;值用举行面积表示
  • 条形图:各柱之间有间隙,表示独立的、不连续分类变量;值用矩形长度表示

案例:1班和2班语文成绩统计数据可视化

# 成绩数据
h1 = [ 88.2,  83.5,  68.8,  85.4,  78.6,  69.3,  60.6,  91.2,  52.7,
        85.9,  57.1,  68. ,  66.6,  78.2,  78.8,  85. ,  89.1,  74.4,
        93.6,  75.7,  54.3,  55. ,  90.9,  79.4,  94.4,  86.7,  82.4,
        76.7,  78.7,  72.3,  83.9,  78.6,  80. ,  70.5,  87.1,  80.3,
        87.9,  65.1,  67.4,  61.5,  49.7,  77.1,  91.4,  72. ,  61.5,
        73.9,  76.9,  88.2,  51.2,  53.9]

h2 = [ 79.5,  99. ,  80. ,  71. ,  79.2,  85.6,  79.2,  68.8,  68.7,
        96.5,  63.8,  81.8,  76.9,  80. ,  73.8,  77.1,  79.6,  76.8,
        73.9,  73.2,  66. ,  76.2,  76.4,  65.3,  75.2,  74.5,  87.5,
        78.4,  95. ,  72.6,  86. ,  71.7,  71. ,  87.7,  83.9,  76.8,
        72.3,  67. ,  67.8,  79.6,  81.9,  83. ,  65.6,  91.6,  75.5,
        77.6,  82.8,  87.5,  75.1,  79.4]

plt.hist(h1)

(array([ 4.,  3.,  3.,  3.,  5.,  4., 11.,  5.,  7.,  5.]),
 array([49.7 , 54.17, 58.64, 63.11, 67.58, 72.05, 76.52, 80.99, 85.46,
        89.93, 94.4 ]),
 <a list of 10 Patch objects>)

plt.hist(
    h1,  # 直方图数据
    10,  # 直方个数
    density=1,  # 默认0 数据出现个数,1 出现个数归一化为出现的频率
    histtype='bar',  # 直方图样式:默认bar,stepfilled填充颜色,step不填充只有线条
    facecolor='gray',  # 直方图颜色
    edgecolor='g',  # 直方图边框颜色
    alpha=0.3,
)

# 直方图叠加
plt.hist(h2, 10, density=1, histtype='bar', alpha=0.3)
plt.show()


箱线图

箱线图又名盒须图,是一种用作显示一组数据离散情况的统计图表,常用作多组数据的综合统计比较

四分位数:
第一四分位数(Q1),又称“较小四份位数”,等于该样本中所有数值由小到大排列后第25%的数字。
第二四分位数(Q2),又称“中位数”,等于该样本中所有数值由小到大排列后第50%的数字。
第三四分位数(Q3),又称“较大四分位数”,等于该样本汇总所有素质由小到大排列后第75%的数字

箱线图主要包含5个统计量,从上到下,从高到低:

最大非异常值,上边线
Q3,箱体上边缘上四分位数
Q2,中位数线
Q1,箱体下边缘下四分位数
最小非异常值,下边线
除了上面5个统计量,上下边缘外侧可能还有异常值

Q3和Q1的差值,即四分位数差

  • 大于Q1 1.5倍四分位数差的值,或者小于Q1 1.5倍四分位数差的值,划为异常值
a = [15,5,9,22,4,-5,45,-22]

plt.boxplot(a)

plt.show()

案例:某班级a/b/c三组学员数学成绩统计分析可视化

组别\编号   1   2   3   4   5   6   7   8
a   42  55  79  68  15  98      
b   32  59  77  100 92  88  5   0
c   92  98  78  65  97  100 0
a = [42,55,79,68,15,98]
b = [32,59,77,100,92,88,5,0]
c = [92,98,78,65,97,100,0]

plt.boxplot(
    (a, c, b),
    labels=('a','c','c'),  # 标签
    
    showfliers=True,  # 是否显示异常值,默认显示
    whis=1.5,  # 指定异常值参数:默认1.5倍四分位差
    showmeans=True,  # 是否显示平均值,默认不显示
    meanline=True,  # 是否用线标识平均值,默认用点
    
    widths=0.5,  # 柱子宽度
#     vert=False,  # 默认True纵向,False横向
    patch_artist=True,  # 是否填充颜色
    boxprops={'facecolor':'#ffff00','color':'green'},  # 箱体样式
)
plt.show()


众数、平均数、中位数的区别

  • 众数:出现频率最高的数,没什么用
  • 平均数:对极端值非常敏感
  • 中位数:对极端值不敏感

总结:
比三打分之所以使用平均数,利用平均值的敏感(中位数会出现大量的相同分数)

同时为了降低平均值的敏感程度,去掉最高分和最低分

import numpy as np
a = [1,2,3,4,5,6,7,8,9,10,11]

# 平均数,中位数
np.mean(a), np.median(a)
(6.0, 6.0)
a = [1,2,3,4,5,6,7,8,9,10,11,1000]

# 平均值,中位数
np.mean(a), np.median(a)
(88.83333333333333, 6.5)

热力图

热力图以二维形式展示数据的大小,主要用于数据的重要程度/相关度展示

a = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]
plt.imshow(a)
<matplotlib.image.AxesImage at 0xda572b0>

plt.imshow(
    a,  # 数据
    cmap='gray',  # 配色,gray灰度
    origin='lower',  # 水平翻转,默认upper,lower
    interpolation='lanczos',  # 渲染,模糊
)

plt.colorbar()  #侧栏
<matplotlib.colorbar.Colorbar at 0xdada7b8>

例子:可视化班级同学成绩和作为关系

a = np.random.randint(0, 100, (10, 10))
a
array([[29, 21, 18, 51,  2, 91, 50, 38,  5, 32],
       [30, 73, 54, 52, 83, 80, 69, 46, 72, 50],
       [89, 45, 14, 11, 36,  9,  8, 94, 41, 80],
       [47, 43, 83, 35, 59, 49, 70, 99, 94, 87],
       [ 4, 52, 69, 15, 47, 18, 80, 54, 48, 63],
       [24, 66, 37,  8, 64, 41, 74, 96,  2, 43],
       [29, 49, 48, 59, 85, 87, 42, 32, 90, 77],
       [68, 22, 67,  0, 25, 77, 12, 53, 39, 79],
       [ 1, 98, 28, 57, 20, 11, 86, 53, 61, 13],
       [14, 71, 47, 48, 67,  1, 20, 35, 68, 57]])
# 设置图像大小
plt.figure(figsize=(10,10))

plt.imshow(
    a,  # 数据
    cmap='gray',  # 配色,gray灰度
    interpolation='lanczos',  # 渲染,模糊
)
# 设置x轴,y轴内容
plt.xticks([0,1,2,3,4,5,6,7,8,9])
plt.yticks([0,1,2,3,4,5,6,7,8,9])

plt.grid()  # 网格
plt.colorbar()  # 侧栏
<matplotlib.colorbar.Colorbar at 0xc57cb38>

# 叠加图像到背景上

# 彩色图像
b = [
    [[255, 0, 1],[255, 0, 22],[255, 0, 33],[255, 0, 44]],
    [[255, 0, 51],[255, 0, 62],[255, 0, 73],[255, 0, 84]],
    [[255, 0, 91],[255, 0, 102],[255, 0, 113],[255, 0, 124]],
]
plt.imshow(b)
<matplotlib.image.AxesImage at 0xde31898>

img = plt.imread('code/images/xiangnong.jpg')  # 将图像转为数组
img
array([[[140, 122, 100],
        [103,  90,  74],
        [ 88,  78,  69],
        ...,
        [211, 199, 175],
        [181, 169, 145],
        [178, 164, 138]],

       [[118, 102,  79],
        [112, 100,  86],
        [ 82,  73,  64],
        ...,
        [204, 192, 168],
        [177, 165, 141],
        [176, 162, 136]],

       [[248, 233, 212],
        [215, 208, 192],
        [126, 122, 111],
        ...,
        [216, 204, 180],
        [194, 182, 158],
        [196, 182, 156]],

       ...,

       [[ 86,  76,  66],
        [ 84,  74,  65],
        [ 82,  73,  64],
        ...,
        [ 96,  88,  77],
        [ 84,  76,  65],
        [ 72,  66,  54]],

       [[ 88,  79,  70],
        [ 87,  78,  69],
        [ 91,  84,  76],
        ...,
        [ 63,  64,  59],
        [ 59,  60,  55],
        [ 71,  71,  69]],

       [[ 93,  79,  68],
        [103,  89,  78],
        [ 94,  80,  69],
        ...,
        [ 66,  65,  61],
        [ 68,  67,  62],
        [ 72,  69,  64]]], dtype=uint8)
plt.imshow(img)
<matplotlib.image.AxesImage at 0xe250358>

extent = (0, 25, 0, 25)  # 按 左右下上 位置拉伸填充图像
plt.imshow(img, extent=extent)

# 将新图叠加到上图之上 散点图
plt.scatter(
    [12.5, 15.5],
    [19, 19.5],
    s=[100, 200],
    color='r',
    alpha=0.7,
)

plt.axis("off")  # 去掉坐标轴
(0.0, 25.0, 0.0, 25.0)

posted @ 2018-12-12 16:35  木子章  阅读(3190)  评论(0编辑  收藏  举报