Python可视化——基于matplotlib.pyplot的基础图形绘制

目录

一、 本文简介

二、 基本图形

2.1 柱状图

2.1.1 普通柱状图

2.1.2 堆积柱状图

2.1.3 分组柱状图

 2.2 条形图

2.2.1 普通条形图

2.2.2 复式条形图

2.2.3 堆积条形图

 2.3 直方图

2.3.1 普通直方图

2.3.2 概率分布直方图

 2.4 饼图

2.4.1 非分裂饼图(常规饼图)

2.4.2 分列式饼图

2.4.3 环形图

 2.5 散点图

 2.5 极线图(雷达图)

2.5.1 普通极线图

2.5.2 雷达图

2.5.3 复式雷达图

2.6 箱线图 

 三、 总结


一、 本文简介

        本文基于python的matplotlib库进行基本图形的绘制,包括:柱状图,条形图,直方图,饼图,极线图,气泡图(散点图),箱线图。但不会很死磕参数,作者能力有限,平时写论文最常用的只有几个,望读者见谅。关于这几类图的作用,本文会有所提及,但不深。作者认为实践出真知,用多了,自然就知道该用什么了。

        希望本文可以给各位读者提供一定的帮助。作者也在不断学习,有什么写错的地方,欢迎批评指正。本文要导入的库如下。

import matplotlib.pyplot as plt
import numpy as np

        如果希望做出来的图形可以使用中文标注的情况 ,需要导入以下代码。其中的SimHei是黑体的意思,如果需要设置特定字体,可以去查阅其他资料。

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

二、 基本图形

2.1 柱状图

        bar():柱状图在于展示不同类别或者不同时间上的数据差异。基本参数有:

bar(x,y,width,bottom,align,hatch,color,lw,tick_label,edgecolor,label...)
参数解释及使用
x 柱子在x轴上的坐标,也可以是字符串序列
y 柱子的高度,即y轴上的值,也可以理解为要展示的值。浮点数,支持列表和ndarray(numpy数组)
width 柱子的宽度,默认是0.8。设置width,可以绘制分组柱状图
bottom bottom,柱子的基准高度,默认0开始,当数值较大时可以设置较符合的基准高度,突出差异
align 柱子在x轴上的对齐方式,可以设置center和edge,center即居中,edge时靠右,若想靠左,需要同时设置width为负数
hatch 柱子的填充符号,可以使用/,|,-,+,x,o,O,.,*,\(易作为转义字符)等。
color 柱子填充颜色,字符串,可以固定一个值,也接受字符串数组
lw linewidth的简写,柱子边框的宽度,浮点数。与此类似的还有linestyle(简写:ls)
tick_label 可以设置x轴上的标签,数组类型
edgecolor 柱子的边框颜色,可以指定一个颜色,也可以指定一个数组
label 要展示的图例,字符串,需要配合plt.legend函数一起使用。但如果设置的颜色不是统一的或者说在分组柱状图中展示,只会显示第一个出现的颜色并标上意思。

2.1.1 普通柱状图

        carray和earray中的颜色是填充颜色的简写,如果要设置独特的颜色,需要完整输入。

x = [1, 2, 3, 4, 5]
# x = list("ABCDE")
y = [2.3, 2.6, 3.7, 4.1, 4.7]
width = [0.8, 0.2, 0.3, 0.5, 0.1]
carray = ['r', 'g', 'b', 'c', 'm']  # 柱子填充颜色
earray = ['r', 'y', 'k', 'g', 'b']  # 边框颜色
linewidth = 0.2
tlabel = ["a", 'b', 'c', 'd', 'e']
plt.bar(x, y, width=width, align="center",
        bottom=None,
        lw=linewidth,
        tick_label=tlabel,
        color=carray, 
        edgecolor=earray,
        hatch='+',  # 柱子填充符号
        label="zzzz") 
plt.legend()
plt.show()

        效果如下,可以发现,在图列部分,也会将填充的符号包括进去。x轴上的值是可以自定义的,也可以用plt.xticks()设置。

 2.1.2 堆积柱状图

        堆积柱状图,可以显示一种大类下某种小类的占比,在matplotlob中,就是多画一个柱状图进行覆盖。但需要注意覆盖的顺序,“大类在前,小类在后”。防止被覆盖住。

x = [1, 2, 3, 4, 5]
y = [2.3, 2.6, 3.7, 4.1, 4.7]
y1 = [1, 1.5, 2.3, 1.8, 3.2]
width = [0.8, 0.2, 0.3, 0.5, 0.1]
carray = ['k', 'g', 'b', 'c', 'm']
earray = ['r', 'y', 'k', 'g', 'b']
linewidth = 0.2
tlabel = ["a", 'b', 'c', 'd', 'e']
plt.bar(x, y, width=width, align="center",
        bottom=None,
        lw=linewidth,
        tick_label=tlabel,
        color=carray,
        edgecolor=earray,
        hatch='/')  # 柱子填充符号
plt.bar(x, y1, width, align="center",
        lw=linewidth, hatch='\\')
plt.show()

        效果如下,需要注意的是,有时会出现没有如此明显的分层,可能的原因在于两个柱状图的顺序不对;或者是y轴的设置不对,造成在某一量纲上差距很小,可以通过改变y轴的范围解决。

 2.1.3 分组柱状图

        前面提到,通过width可以设置,但此时第一个参数x不能为字符串,因在字符串无法和浮点数进行相加。分组柱状图可以显示不同类别的不同分组对比状况。例如不同年度间不同季节的消费人数对比。

x = np.arange(5)
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 8, 5]
bar_width = 0.35
tick_label = [2016, 2017, 2018, 2019, 2020]
plt.bar(x, y, bar_width, color='c', align='center', label='A类', alpha=0.5)
plt.bar(x+bar_width, y1, bar_width,
        color='b', align='center',
        alpha=0.5, label="B类",
        tick_label=tick_label)  # 与堆积柱状图相比,在x轴方向加入数值
plt.xlabel("不同年度不同产品类别销售情况")
plt.ylabel("销售量")
plt.legend()
plt.show()

        结果如下,其实就是通过改变第二幅柱状图在x轴的位置实现。可能发现代码中出现了一个alpha参数,在上面的参数介绍中没出现,它是在**kwargs中,bar中**kwargs是属于Rectange属性中,这边不做过多解释,作者也没怎么搞清楚,不过,这个alpha参数,是透明度的意思,设置柱子的透明度,基本在任意图形绘制中都可以使用。

 2.2 条形图

        barh():和柱状图基本一致的效果,比较不同类别的差距。在某一些场景上,展现效果优于柱状图。基本参数有:

barh(y,width,height,left,align,....
y 表示y坐标轴,接受字符串序列或者int数组,相当于bar中的x
width 即条的宽度,同bar的width
height 同bar中的height
left 相当于bar中的bottom,即设置条的初始位置,接受数组或者int类型

        其他参数基本和bar()函数中一致,这里不再赘述。

2.2.1 普通条形图

        普通的条形图就相当于柱状图旋转了90°。

y = [2, 7, 4, 5, 6]
width = [2.3, 2.6, 3.7, 4.1, 4.7]
height = 0.2
carray = 'b'
earray = 'm'
tlabel = ['cc', 'mm', 'r', 'uu', 'pp']  # y轴上标签
plt.barh(y, width, height,
         align='center',
         tick_label=tlabel,
         edgecolor=earray,
         color=carray,
         left=10)
plt.show()

 2.2.2 复式条形图

         复式条形图对应分组柱状图。注意:无论是复式条形图还是分组柱状图,一定要加上图例

y = np.arange(5)
h = [6, 10, 4, 5, 1]
h1 = [2, 6, 3, 8, 5]
bar_width = 0.35
tick_label = [2016, 2017, 2018, 2019, 2020]
plt.barh(y, h, bar_width, color='c', align='center', label='A类', alpha=0.5)
plt.barh(y+bar_width, h1, bar_width,
         color='b', align='center',
         alpha=0.5, label="B类",
         tick_label=tick_label)  # 与堆积柱状图相比,在x轴方向加入数值
plt.xlabel("不同年度不同产品类别销售情况")
plt.ylabel("销售量")
plt.legend()
plt.show()

 2.2.3 堆积条形图

        对于它的名字,不明白这样讲正不正确,但是意思就是这个意思,也是对比大类中小类的情况,也要注意不同条形图的绘制顺序,防止被覆盖。

y = np.arange(5)
h = [2.3, 2.6, 3.7, 4.1, 4.7]
h1 = [1, 1.5, 2.3, 1.8, 3.2]
width = 0.8
linewidth = 0.2
tlabel = [2017, 2018, 2019, 2020, 2021]
plt.barh(y, h, height=width, align="center",
         lw=linewidth,
         tick_label=tlabel,
         color="blue",
         label="粮食产量")
plt.barh(y, h1, height=width, align="center", color='red',
         lw=linewidth, label="小麦产量")
plt.title("不同年度小麦产量占比")
plt.xlabel("产量/亿吨")
plt.legend()
plt.show()

         效果如下。对于lw,width,作者这边建议,一般情况下,设置一个数值就行,不用设置数组,展示起来很不美观,作图的目的就是直观的展示数据,切勿本末倒置。

 2.3 直方图

         hist():直方图用于展示数据的分布

         和柱状图的区别:

        (1) 柱状图在于比较数据的大小,直方图展示数据的分布情况;

        (2)柱状图柱子间是隔开的,直方图是相邻的。

        (3)柱状图x轴基本是定类数据,而直方图是定量数据

        常用参数有

hist(x, bins=None, range=None, density=False,
        cumulative=False, bottom=None, histtype='bar', 
        align='mid',rwidth=None, log=False, 
        color=None,label=None)
x 整数值或者数组序列
bins 整数或者序列。若为整数,即柱子个数,否则为每个柱子的范围值
range 设置直方图x轴的范围,可以借此剔除一些离群值,格式为(xmin,xmax)
density bool类型,若为True,则显示概率密度
cumulative boo类型,若为True,计算累计频率
bottom 数组或者证书,对应初始位置,和bar和barh一样
histtype 直方图类型。bar表示最普通的;barstacked表示堆叠的直方图;step表示未填充的直方图;
stepfilled表示有填充的直方图,和bar差不了太多
align 柱子位置。left表示柱子的中心位于bins的左边缘;mid为中间;right为右边缘。
rwidth 整数值,柱子宽度占bins宽的比例
log bool类。是否将x轴对数化,降低量纲

        color设置颜色,label设置柱子标签,alpha设置透明度。

2.3.1 普通直方图

x = np.random.normal(size=1000)
plt.hist(x, bins=100, density=False,
         histtype="bar",  # 用于选择条形图的样式
         align="mid",
         alpha=0.6)
plt.show()

         np.random.normal(size=1000)表示生成1000个标准正态分布随机数。

 2.3.2 概率分布直方图

x = np.random.normal(size=1000)
plt.hist(x, bins=100, density=True,
         histtype="bar",  # 用于选择条形图的样式
         align="mid",
         alpha=0.6)
plt.show()

        和普通直方图最大的不同在于y轴的刻度,普通直方图表示的是频数,下图表示概率。 

        

 2.4 饼图

        pie():直观反映一维数据中各项之间的比例大小。但要求数据中没有负值和零值。饼图较常使用的参数比较多,如下:

pie(x, explode=None, labels=None, colors=None, 
        autopct=None,pctdistance=0.6, shadow=False, 
        labeldistance=1.1,startangle=0, radius=1, 
        wedgeprops=None,textprops=None, center=(0, 0),
        rotatelabels=False)
x 一维数组,每个板块占的大小
explode
每个板块相对于饼圆半径的偏移距离,取值为小数。
labels 每个板块的标签,字符串序列
autopct 板块占比标签。%d%%:整数百分比;%0.1f:一位小数;%0.1f%%:一位小数百分比;%0.2f%%:两位小数百分比
pctdistance
板块内标签与圆心的距离。浮点数
shadow 饼图下是否有阴影,略微展现立体感
labeldistance
饼块外标签与圆心的距离
startangle
饼块起始角度。浮点数,默认为 0,即从 x 轴开始,角度逆时针旋转
radius
饼图半径。浮点数,默认为 1,若>1,需要设置好画布大小
wedgeprops
饼块属性。字典,可以设置饼块边框大小,填充颜色等
textpropss
标签的文本属性,字典,可以设置字体、字号、颜色等
center 饼图中心坐标,包含两个浮点数元素的元组
rotatelabels
bool类型,饼块外标签是否按饼块角度旋转。

2.4.1 非分裂饼图(常规饼图)

x = [10, 30, 50, 20, 45]
colors = ['#377eb8', "#4daf4a", "#984ea3", "#ff7f00", "#e7c3b2"]  # 颜色
labels = ['A', 'B', 'C', 'D', 'E']
plt.pie(x, colors=colors, labels=labels,
        autopct='%0.1f%%',
        startangle=45,
        pctdistance=0.7,
        labeldistance=1.2)
plt.show()

 2.4.2 分列式饼图

labels = ['A类', 'B类', 'C类', 'D类', 'E类']
x = [0.35, 0.20, 0.15, 0.05, 0.25]
colors = ['r', 'g', 'b', 'c', 'm']
explode = [0.1, 0.2, 0.05, 0.1, 0.06]  # 每个板块相对于饼原半径的偏移距离
wedgeprops = {'linewidth': 1, 'edgecolor': "black"}
plt.pie(x, explode, labels, colors,
        pctdistance=0.6,  # 板块内标签与圆心的距离
        autopct='%0.2f%%',  # 板块内的标签
        shadow=True,
        labeldistance=1.1,  # 饼块外标签与圆心的距离
        startangle=0.00,  # 饼块的其实角度
        radius=1,  # 兵源半径
        wedgeprops=wedgeprops,  # 饼块的属性
        textprops={'fontsize': 12, 'color': 'black', "font": 'Kaiti'},
        center=(0, 0),  # 饼原中心坐标
        rotatelabels=False)  # 饼块外标签是否按照饼块角度旋转
plt.show()

         分裂饼图最主要的参数即为explode。分裂饼图可以突出某一项所占比例,使得用户第一眼可以聚焦到想看到的地方。

 2.4.3 环形图

        在matplotlib中,环形图的原理即在一个圆中减去一个小圆,即用和背景颜色相同的单位圆覆盖住中间位置。

x = [15, 20, 17, 25]
explode = (0, 0.1, 0, 0)
label = ['a', 'b', 'c', 'd']
x_0 = [1, 0, 0, 0]
plt.pie(x, explode,
        labels=label,
        autopct="%3.1f%%",
        startangle=90,
        shadow=True)
plt.pie(x_0, radius=0.5, colors='w')
plt.axis('equal')
plt.show()

        环形图要显示好标签,需要设置标签距离圆心的位置,确保足够美观。单位圆即只有一类,其余类没有,或者为0。 

 2.5 散点图

        scatter():也称为气泡图。散点图可以展示两组数据中的关系,或者分析一种趋势,和折线图的作用有点类似。基本参数如下:

scatter(x, y, s=None, c=None, marker=None, 
        norm=None, vmin=None, vmax=None, alpha=None, 
        linewidths=None,edgecolors=None)
x,y 对应二维坐标轴上的坐标,分别对应x轴、y轴
s
指定图点的大小,默认 20
c
指定散点图的颜色,默认为蓝色
marker
指定散点的形状,默认为空心圆。可以设置:. , o v ^ > < * | _ + x d 
norm
设置数据亮度,范围0-1,使用该参数时仍需要参数 c 
linewidths
设置散点边界线的宽度
edgecolor
设置散点边界线的颜色
vmin,vmax
亮度设置,与 norm 类似,如果使用 norm 参数,此参数无效

alpha即设置散点的透明度。示例如下:

x = np.random.randn(1000)  # 返回1000个样本服从标准正态的数
y = np.random.randn(1000)
plt.scatter(x, y,
            s=20,  # 指定点的大小,若传入一维数组,则表示每个点的大小
            c='g',
            marker='o',  # 指定散点形状
            vmin=0, vmax=20,
            alpha=0.5,
            linewidths=1,
            edgecolors='c')
plt.show()

 2.5 极线图(雷达图)

        polar():雷达图可以很好的对比不同个体在各个指标上的差异。也可以体现个体在各个方面的平衡。常用参数如下:

polar(thera,r,marker,linestyle,linewidth,color,ms...)
thera 每个标记所在射线于极径的角度
r 标记点到原点的距离
marker 标记点样式,有 . , o v ^ > < * | + _ x d
linestyle 线的样式,-,--,-.,:
linewidth 浮点数,线的宽度
color 线的颜色
ms 标记点的大小

2.5.1 普通极线图

angles = np.linspace(0, 2*np.pi, 6)
r = np.random.randint(1, 10, 6)
plt.polar(angles, r)
plt.show()

        np.linspace表示从0~2Π均匀分成6个数,random.randint(1,10,6)表示在1-10中选6个数,普通极线图是没有闭合的。效果如下。 

 2.5.2 雷达图

        区别于普通的极线图,雷达图是闭合的。若要在极坐标上添加标签,需要使用此函数:plt.thetagrids()。

angles = np.linspace(0, 2*np.pi, 6)
labels = ['能力A', '能力B', "能力C", "能力D", "能力E", "能力F"]
r = np.random.randint(1, 10, 6)
r = np.append(r, r[0])
angles = np.append(angles, angles[0])
plt.polar(angles, r)
plt.thetagrids(angles=(np.linspace(0, 360, 6)), labels=labels, fontsize=15)
plt.show()

(注:有时候angles即角度用0到2\pi的方法会导致绘制出来的图像一条直线,可以换成0到360) 

        想让极线图闭合,在matplotlib中,即在r中添加最初的位置,角度也要加上去。thetagrids的第一个参数是角度,第二个是标签。

若想要中间有填充效果,可以使用fill函数进行添加。

函数为:plt.fill(thera,r,color,alpha) ,效果如下:

angles = np.linspace(0, 2*np.pi, 6)
labels = ['能力A', '能力B', "能力C", "能力D", "能力E", "能力F"]
r = np.random.randint(1, 10, 6)
r = np.append(r, r[0])
angles = np.append(angles, angles[0])
plt.polar(angles, r, marker='*', lw=1, ls='--', ms=10, color='r')
plt.thetagrids(angles=(np.linspace(0, 360, 6)), labels=labels, fontsize=15)
plt.fill(angles, r, color='r', alpha=0.25)
plt.show()

 2.5.3 复式雷达图

        其实就是多个对象之间不同能力的对比,相比较分组柱状图,更加直观。

angles = np.linspace(0, 2*np.pi, 6)
labels = ['能力A', '能力B', "能力C", "能力D", "能力E", "能力F"]
r = np.random.randint(1, 10, 6)
r = np.append(r, r[0])
r1 = np.random.randint(1, 10, 6)
r1 = np.append(r1, r1[0])
angles = np.append(angles, angles[0])
plt.polar(angles, r, marker='*', lw=1, ls='--', ms=10, color='r', label="A")
plt.thetagrids(angles=(np.linspace(0, 360, 6)), labels=labels, fontsize=15)
plt.fill(angles, r, color='r', alpha=0.25)
plt.polar(angles, r1, marker='*', lw=1, ls='--', ms=10, color='g', label="B")
plt.fill(angles, r1, color='m', alpha=0.25)
plt.legend()
plt.show()

2.6 箱线图 

         boxplot():可以展示一组数据的分散情况,直方图虽然也能查看分散情况,但不够明显。参数如下:

boxplot(x, notch=None, sym=None, vert=None, whis=None,
        positions=None, widths=None, patch_artist=None,
        bootstrap=None, usermedians=None, conf_intervals=None,
        meanline=None, showmeans=None, showcaps=None, showbox=None,
        showfliers=None, boxprops=None, labels=None, flierprops=None,
        medianprops=None, meanprops=None, capprops=None,
        whiskerprops=None)
x 指定数据,可以是一维数组,也可以是多维,即绘制多个图
notch
bool类型,是否凹口的形式展示箱线图,默认非凹口
sym
指定异常点的形状,默认为+号显示
vert
bool类型,是否需要将箱线图垂直摆放,默认垂直拜访
whis
指定上下须与上下四分位的距离,默认为 1.5 倍的四分位差
positions
指定箱线图的位置
widths
指定箱线图的宽度,默认为 0.5
patch_artist
是否填充箱体的颜色
meanline
bool类型,是否用线的形式表示均值,默认用点来表示
showcaps
bool类型,是否显示箱线图顶端和末端的两条线,默认显示
showmeans
是否显示均值,默认不显示
showbox
bool类型, 是否显示箱线图的箱体,默认显示
showfliers
bool类型, 是否显示异常值,默认显示
boxprops
设置箱体的属性,如边框颜色,填充色等
labels
为箱线图添加标签,类似于图例的作用
filerprops
设置异常值的属性,如异常点的形状、大小、填充色等
medianprops
设置中位数的属性,如线的类型、粗细等
meanprops
设置均值的属性,如点的大小、颜色等
capprops
设置箱线图顶端和末端线条的属性,如颜色、粗细等
whiskerprops
设置须的属性,如颜色、如粗细、线的类型等

        乍一看,箱线图的参数特别多,但是基本使用,只需要把x输入即可,其他都是特殊情况下的定制。

        如何看箱线图?以上图为例,最上方和最下方的两条线是上下限。箱体上下的两条箱线即对应四分位数(y轴看是对应2和7),中间黄色的线即为均值。

x = np.arange(10)
plt.boxplot(x,
            sym='o',
            vert=None,  # 是否将箱线图垂直摆放
            widths=0.8,  # 设置箱线图宽度
            patch_artist='g',  # 是否填充箱体颜色
            showmeans=True,
            meanprops={'marker': 'o', 'markerfacecolor': 'red', 'markersize': 5})
plt.show()

         如果要在一张图上画多个箱线图,输入的x是多维数据即可。图中meanprops的参数也可以类似地用在其他参数上。

x = np.arange(10)
y = np.arange(3, 12)
plt.boxplot([x, y],
            sym='o',
            vert=None,  # 是否将箱线图垂直摆放
            widths=0.8,  # 设置箱线图宽度
            patch_artist='g',  # 是否填充箱体颜色
            showmeans=True,
            meanprops={'marker': 'o', 'markerfacecolor': 'red', 'markersize': 5})
plt.show()

 三、 总结

        作者认为,常用的图就这些,无论是在学习还是在工作上,这些只是基本的图形。如果需要美化,可以结合上一篇文章Python可视化——matplotlib.pyplot绘图的基本参数详解。以及通过更加丰富的色彩进行展示。当然数据才是最重要的,作图的目的是为了更加直观的看清楚数据的情况。        

        如有写错或者不明白的地方,可以在评论区或者私信作者,欢迎各位读者批评指正。创作不易,可以的话,点赞、关注、收藏!!!

猜你喜欢

转载自blog.csdn.net/qq_60471758/article/details/128365567