matplotlib 绘图详解

matplotlib

Matplotlib是一个帮助我们绘制数据的python库。通过它,你可以画出线图、散点图、等高线图; 条形图、直方图、3D 图形甚至是图形动画等等。

当横轴为时间时,使用线图
当两个变量存在相关性时,使用散点图
当想要观察数值数据的分布时,使用直方图
我们可以在图表中定义以下属性:颜色、标签、线宽、标题、不透明度、网格、图形大小、坐标轴刻度、线型等

条形图

  • 条形图一种以长方形的长度为变量的表达图形的统计报告图,由一系列高度不等的纵向条纹表示数据分布的情况,用来比较两个或以上的价值(不同时间或者不同条件),只有一个变量,通常利用于较小的数据集分析

    • 条形图:柱形图、堆积柱形图、百分比堆积柱形图等。
    • 适用场景
      1. 适合分析分类数据字段、或者连续的数据字段,利用柱子的高度来反映数据的数值差异。、
      2. 适合分析对比组内各项数据
      3. 堆积柱:可以形象的展示一个大分类包含的每个小分类的数据,以及小分类的占比情况,显示的是单个项目与整体之间的关系
      4. 百分比堆积柱形图:矩形高度表示每子项占当前项的百分比
  • 案例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x=np.arange(1,6)
y=np.random.randint(1,100,5) #随机生成5个1到100之间的数

条形图:维度分类较多或维度名称比较长的时候使用横向树状图(条形图)

plt.bar(x,y,color='g')
plt.show()

堆积图:更直观对比整体的数据,可以更清晰的看出各种类别的占比情况

y.plot(kind='barh',stacked=True,figsize=(16,9)) #传递参数stacked=True来生成堆积树状图
plt.show()

百分比堆积树状图:展示的占比的情况

y.div(data.sum(1),axis=0).plot(kind='barh',figsize=(16,9),stacked=True)
plt.show()

直方图

  • 直方图又称质量分布图,是一种统计报告图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据类型,纵轴表示分布情况。用来整理计量值的观测数据,分析其分布状态的统计方法,用于对总体的分布特征进行推断

    应用场景:表示分布状态,分析数据是否服从正态分布,判断数据是否异常或者孤立

  • 直方图与柱状图的比较:

    • 直方图展示数据的分布,柱状图比较数据的大小。这是直方图与柱状图最根本的区别。直方图表示在一定值的区间中,有多少数据,表现的是数据的分布情况。柱状图表示,每一个数据的值的大小,表现的是值大小的对比

    • 直方图X轴为定量数据,柱状图X轴为分类数据。 直方图的x轴通常是连续排列的,柱状图是分开排列的

  • 柱状图是以矩形的长度表示每一组的数据大小,其宽度(表示类别)则是固定的,利于较小的数据集分析

  • 直方图是以矩形的长度表示每一组的频数或频率,宽度则表示各组的组距,因此其高度与宽度均有意义,利于展示大量数据集的统计结果

  • 画直方图一般流程

    • 计算极差(最大值 - 最小值)
    • 设置组距
    • 计算组数(极差/ 组距)(通常对于数据较少的情况,分为5 ~ 12组 )
  • 案例

x=np.random.randn(500)
plt.hist(x,bins=20,color='g',rwidth=0.5)
plt.show()

散点图

  • 散点图用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。散点图将序列显示为一组点。值由点在图表中的位置表示。

    应用场景:判断两个变量之间是否存在关联,判断异常值

  • 探究 投资额和住宅投资的关系

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
x=np.arange(10)
y_c=np.random.normal(size=10)
plt.scatter(x,y_c,color='y')

饼图

  • 饼图用于表示不同分类的占比情况,通过弧度大小来对比各种分类。饼图通过将一个圆饼按照分类的占比划分成多个区块,整个圆饼代表数据的总量,每个区块(圆弧)表示该分类占总体的比例大小,所有区块(圆弧)的加和等于 100%。

    应用场景:分类占比

  • 每个省份投资额占比

from matplotlib import pyplot as plt
a=np.random.randint(1,10,5)
plt.pie(a,autopct="%1.2f%%",shadow=True,explode=(0,0,0.3,0,0),startangle=90)
plt.show()
  #让饼图保持正圆形
  plt.axis('equal')
  plt.show()

参数解释:
y 为dataframe列名,或者列名列表,当绘制多列数据,指定subplots=True,绘制在不同的子图中
autopct:在图中显示百分比
shadow:布尔值,为饼图增加阴影效果
explode:为饼图增加破裂效果,值越大,破裂越大
startangle:饼图旋转角度,从X轴逆时针旋转

折线图

  • 折线图可以很直观的反应出数据的变化趋势,反应事物的变化情况

    • 应用场景:适合二维的大数据集,还适合多个二维数据集的比较
  • 案例

    • 绘制标普500指数的收盘价的变化

      import numpy as np
      import pandas as pd
      import matplotlib.pyplot as plt
      
      data = pd.read_csv('d:/test_data/spx.csv',index_col='Unnamed: 0',parse_dates=True) #index_col:DataFrame的列用作行索引, parse_dates:解析索引
      
      data.head()
                  SPX
      1990-02-01  328.79
      1990-02-02  330.92
      1990-02-05  331.85
      1990-02-06  329.66
      1990-02-07  333.75
      
    • 面向对象画图

      #创建画布
      fig,ax=plt.subplots(figsize=(16,6),dpi=100)
      #准备数据
      x=data.index
      y=data['SPX']
      ax.plot(x,y,color='r')
      plt.show()
      
*在图中截取2007-2010年金融危机部分*

```python
#截取2007-2011年
#set_xlim, setylim:设置图表的边界

ax.set_xlim(['2007-1-1','2011-1-1'])

#截取SPX>600
ax.set_ylim([600,1800])

#添加标题
ax.set_title('2007-2010年金融危机标普500指数变化趋势')

#添加坐标轴标签
ax.set_xlabel('Date')
ax.set_ylabel('SPX')
```

*在图中添加文字*

```python
# ax.annotate('Peak of bull market',xy=(datetime(2007,10,11),y['2007-10-11']),
           xytext=(datetime(2007,10,11),y['2007-10-11'] + 160),
           arrowprops=dict(facecolor='c'))
"""
s:字符串,注释文本
xy:注释的点(x,y)
xytext:放置文本的位置(x,y)
arrowprops:在xy和xytext之间绘制箭头的属性(字典)
"""

crisis_date = [
    (datetime(2007,10,11),'Peak of bull market'),
    (datetime(2008,3,12),'Bear Stearns Fails'),
    (datetime(2008,9,15),'Lehman Bankruptcy')
]

for date,label in crisis_date:
    ax.annotate(label,xy=(date,y[date]),xytext=(date,y[date]+160),
               arrowprops=dict(facecolor='c'))
```



*关于annotate更多请参考:*

*https://matplotlib.org/api/_as_gen/matplotlib.pyplot.annotate.html*

*https://matplotlib.org/users/annotations_intro.html*

*在这里我们另外补充了面向对象画图的另外几个功能*
  • Dataframe画图

    在前面我们都是直接使用 matplotlib进行绘图,我们的pandas集成了matplotlib画图的方法,我们也可以还有 pandas直接进行绘制

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from datetime import datetime
    
    data = pd.read_csv('d:/test_data/spx.csv',index_col='Unnamed: 0',parse_dates=True)
    
    data.plot(figsize=(16,6),color='r',
              xlim=['2007-1-1','2011-1-1'],
              ylim =[600,1800],
             title='2007-2010年金融危机标普500指数变化趋势'
             )
    #plt.xlim(['2007-1-1','2011-1-1'])
    #plt.ylim([600,1800])
    plt.xlabel('Date')
    plt.ylabel('SPX')
    
    crisis_date = [
        (datetime(2007,10,11),'Peak of bull market'),
        (datetime(2008,3,12),'Bear Stearns Fails'),
        (datetime(2008,9,15),'Lehman Bankruptcy')
    ]
    for date,label in crisis_date:
        plt.annotate(label,xy=(date,y[date]),xytext=(date,y[date]+160),
                   arrowprops=dict(facecolor='c'))
    plt.show()
    
    
  • 我们使用dataframe画图,当不能满足于我们的需求时,可以和 plt方法,或者面向画图方法结合使用

箱线图

  • 箱线图是一种直观简洁的方式去呈现一组数据的分布. 因其形状如箱子而得名. 箱线图广泛用于各个数据分析领域. 它能非常简单明了地显示一组数据中5个重要数值, 最大值 (Maximum Value), 最小值 (Minimum Value), 中位数 (Median Value), 下四分位数 (First Quartile), 上四分位数 (Third Quartile). 箱线图还能发现一组数据中的存在的异常值 (Outliers).

    分位数把所有数值由小到大排列并分成四等份,处于三个分割点位置的数值就是四分位数。

  • 🐉查看投资数据的异常值

x=np.random.randint(1,11,10)
plt.boxplot(x)
print(x)
plt.show()

matplotlib参数调整

  • 在前面我们已经知道了matplotlib图的结构,下面我们着重于matplotlib的辅助显示,颜色,标记,线类型,刻度,标签,图例,以及图片保存

  • 模拟股票10分钟的变化趋势

    • 画出股票趋势图
    import numpy as np
    import pandas as pd 
    import matplotlib.pyplot as plt
    
    #1)准备数据
    x = range(1,11) #股票10分钟
    y = np.random.normal(size=10) #正态分布随机生成10个数据
    
    #2)创建画布
    fig = plt.figure(figsize=(16,6),dpi=100) #设置大小,设置dpi
    
    #3)绘制折线图
    plt.plot(x,y)
    
    #4)显示图像
    plt.show() #show方法会释放figure资源
    
  • 设置刻度标签,设置刻度值

    plt.xticks(x,kwargs):x:显示的刻度值

    plt.yticks(y,kwargs):y:显示的刻度值

    #构造刻度标签
    x_ticks_label = ['10点{}分'.format(i) for i in x]
    
    plt.xticks(x,x_ticks_label,rotation=45) #rotation:将刻度标签旋转多少度
    
  • 设置轴标签,标题

    #设置x,y轴标签
    plt.xlabel('时间') 
    plt.ylabel('涨幅')
    
    #设置图像标题
    plt.title('股票10分中的涨幅')
    
  • 设置颜色,标记和线类型

    #设置颜色color
    #设置线类型linestyle
    #设置标记marker
    plt.plot(x,y,color='r',linestyle='--',marker='o')
    
  • 显示图例

    可能我们在一个绘图区,需要绘制多个图形,多次plot就可以解决

    #在添加一条数据
    y_B = np.random.normal(size=10)
    
    #进行绘制
    #plt.plot(x,y_B,color='b',marker='o')
    
    #添加图例
    #显示图例我们需要先加上label标签
    plt.plot(x,y,color='r',linestyle='--',marker='o',label='A')
    plt.plot(x,y_B,color='b',marker='o',label='B')
    plt.legend(loc='best')
    
    #添加网格显示
    plt.grid(True,linestyle='--',alpha=1) #appha:透明度
    
  • 常见颜色

    标识 描述
    r 红色
    g 绿色
    b 蓝色
    w 白色
    c 青色
    m 洋红
    y 黄色
    k 黑色
  • 常见线类型

    标识 描述
    - 实线
    -- 虚线
    -. 点划线
    点虚线
    ‘’ 空格
  • 常见标记

    标识 描述
    '.' point marker
    ',' pixel marker
    'o' circle marker
    'v' triangle_down marker
    '^' triangle_up marker
    '<' triangle_left marker
    '>' triangle_right marker
    '1' tri_down marker
    '2' tri_up marker
    '3' tri_left marker
    '4' tri_right marker
    's' square marker
    'p' pentagon marker
    '*' star marker
    'h' hexagon1 marker
    'H' hexagon2 marker
    '+' plus marker
    'x' x marker
    'D' diamond marker
    'd' thin_diamond marker
    '|' vline marker
    '_' hline marker
  • 显示图例位置

    位置的字符串 位置的标识
    best 0
    upper right 1
    upper left 2
    lower left 3
    lower right 4
    right 5
    center left 6
    center right 7
    lower center 8
    upper center 9
    center 10

matplotlib图像构造

  • 实现一个简单的matplotlib画图

    import numpy as np
    import matplotlib.pyplot as plt
    
    data= np.arange(10)
    plt.plot(data) #折线图函数
    plt.show()#输出图像
    
  • Part of a Figure

    • matplotlib绘制的图位于 (Figure)对象中

    • Figure:整个图形(可以改变大小和分辨率),想象为画画的画布,可以有任意数量的 Axes,至少要有一个有用

      #创建一个画布
      fig = plt.figure()
      """
      参数:
      figsize:画布大小,默认None,(width,height)整数元组
      dpi:图像分辨率,默认None,整数
      facecolor:背景颜色
      """
      
    • Axes坐标系,数据绘图的区域

    • Axis坐标轴(大小限制,刻度,刻度标签),坐标系中的一条轴

  • 辅助显示层

    辅助显示层为Axes(绘图区)内的除了根据数据绘制出的图像以外的内容,主要包括Axes外观(facecolor)、边框线(spines)、坐标轴(axis)、坐标轴名称(axis label)、坐标轴刻度(tick)、坐标轴刻度标签(tick label)、网格线(grid)、图例(legend)、标题(title)等内容。

  • 图像层

    图像层指Axes内通过plot、scatter、bar、histogram、pie等函数根据数据绘制出的图像。

matplotlib绘制子图

  • 我们在程序中尽量采用面向对象进行绘图,有利于我们可以绘制多个子图,这里为了大家更方便的理解,给出一般的画图流程
  • plt.subplots:(nrows,ncols,sharex,sharey,fig_kw)

    参数 描述
    nrows 子图的行数
    ncols 子图的列数
    sharex 子图共享x轴刻度,默认:False
    sahrey 子图共享y轴刻度,默认:False
    **fig_ky 生成画布时使用额外的关键字参数

    *subplots创建一个新的画布,返回是一个元组,包含 figure对象,生成子图对象的 Numpy数组, 我们在选择子图对象时,可以使用索引进行选取,同时我们在相同比例下进行数据对比的时候可以使用 sharex,sharey来让子图拥有相同的 x轴或 y轴刻度.

    #创建一个包含4个子图对象的figure,默认生成1个
    plt.subplots(2,2,figsize=(16,6),dpi=100)
    #返回一个元组,里面包含了figure对象,以及4个子图对象
    #选取子图进行绘制,选取第二行的第二个进行绘制
    #准备数据
    fig,axs = plt.subplots(2,2,figsize=(16,6),dpi=100,sharex=True,sharey=True)
    x=[1,2,3,4,5]
    y=[0.6,0.8,-0.3,0.2,-0.1]
    #选取我们所需的子图我们使用数组索引
    axs[1,1].plot(x,y)
    

从上图我们可以看出,我们子图和子图之间默认会有一定的间距,我们可以使用subplots_adjust对间距进行调整

subplts_adjust(wspace, hspace)

wspace:宽度百分比:

hspace:高度百分比

#调整子图的间距
plt.subplots_adjust(wspace=0,hspace=0) #消除了子图与子图之间的间距
  • 模拟股票10分钟变化趋势,使用面向对象进行绘图

    使用面向对象绘图有一些基本方法改变:

    set_xticks:设置 x轴的刻度

    set_yticks:设置 y轴的刻度

    set_xticklabes:设置 x轴的刻度标签

    set_yticklabes:设置 y轴的刻度标签

    set_xlabel:设置 x轴标签

    set_ylabe:设置 y轴标签

    set_title:设置标题

    #创建画布,默认生成一个
    fig,ax = plt.subplots(figsize=(16,6),dpi=100)
    
    #面向对象进行画图
    ax.plot(x,y,color='r',linestyle='--',marker='o',label='A')
    ax.plot(x,y_B,color='b',marker='D',label='B')
    
    #显示图例,默认是best
    ax.legend()
    
    #添加网格
    ax.grid(linestyle='--',alpha=1)
    
    #添加标题
    ax.set_title('股票10分中的涨幅')
    
    #设置轴的标签
    ax.set_xlabel('时间')
    ax.set_ylabel('涨幅')
    
    #设置刻度值
    ax.set_xticks(x)
    #设置刻度值标签
    ax.set_xticklabels(x_ticks_label)
    
    #释放figure资源,输出图像
    plt.show()
    
  • 绘制子图
#创建一个2*1的画布
fig,axs = plt.subplots(2,1,figsize=(16,6),dpi=100,sharex=True)

#多个子图进行绘图的时候,我们需要选择我们绘图区(axes)
#选择第一个axes
axs[0].plot(x,y,color='r',linestyle='--',marker='o',label='A')
#选择第二个axes
axs[1].plot(x,y_B,color='b',marker='D',label='B')

axs[0].legend()
axs[1].legend()

axs[0].grid(linestyle='--',alpha=1)
axs[1].grid(linestyle='--',alpha=1)

axs[0].set_title('A股票10分中的涨幅')
axs[1].set_title('B股票10分中的涨幅')

axs[0].set_xlabel('时间')
axs[1].set_xlabel('时间')

axs[0].set_ylabel('涨幅')
axs[1].set_ylabel('涨幅')  

#在创建画布的时候,设置了sharex=True,所有的子图共享x轴刻度
axs[0].set_xticks(x)
axs[0].set_xticklabels(x_ticks_label)

plt.show()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容