【matplotlib】绘图

899 阅读27分钟

参考网址

0/绘图有2种方式

    # matplotlib是扩展包,pyplot是扩展包中的一个模块,及一个.py文件
    import matplotlib.pyplot as plt 
   
    #1/通过plt,初始化总画布fig和子图ax列表
    fig,ax = plt.subplots(2,2,figsize=(20,8),dpi=150) 
    ax1 = ax[0,0]
    ax2 = ax[0,1]
      
    #2/先通过plt创建总画布fig,然后通过add_subplot()在总画布上添加子图
    fig = plt.figure(figsize=(20,8),dpi=200)  
    ax1 = fig.add_subplot(211,polar=False)  # polar参数代表是否创建极坐标,默认是不创建。  
    ax2 = fig.add_subplot(212)

1/什么是matplotlib

matplotlib是一个python的一个库包,用于数据的可视化。
它有一个名为pyplot的模块(模块指的是.py脚本文件),通过提供控制线条样式,字体属性,格式化轴等功能,使得绘图变得容易。
import matplotlib.pyplot as plt 
pyplot是一个.py文件的名字,也就是一个模块,把这个模块抽象出来,命名为plt,然后就可以调用该模块中的所有功能函数了。

主要作用是进行数据的可视化,绘制各种图,比如折线图,柱状图,饼图,散点图,象限图,帕累托图等。
另外,还有像pyecharts,seaborn这样的可视化的扩展包。本篇文章不做赘述。
使用方法:import matplotlib.pyplot as plt

2/figure/axes/axis的区别

figure是总的画布
axes是画布中的子图,也就是每一个绘图的区域。可以在fig中有多个绘图区域。
axis是每个子图中的坐标轴。

image.png

从上图可以知道:
   figure是总画布
   axex是画布中的子图,画布中可以有一个或者多个子图。子图与子图之间是呈矩阵排列的。
   axis是坐标轴,每个子图中都有坐标轴。

image.png

将各个图形绘制在一张画布中,并以矩阵的形式进行排列,就形成了矩阵子图。
子图可以帮我们更方便地对比各数据变化趋势。

在一张画布中,绘制多个子图,可以更直观的对比多个图之间的差别。

3/matplotlib怎么用

<1> 初始化总画布fig和子图axes

import matplotlib.pylot as plt

# 这是第一步,不管干啥,这是第一步
fig,ax = plt.subplots(2,2,
                      figsize=(30,8),
                      dpi=200,
                      facecolor=None,
                      edgecolor=None,
                      frameon=True)   

# plt.subplots()函数的作用是绘制一张总的画布figture,以及任意多个子图的列表对象ax
# axes的个数由该函数的前2个参数决定,根据实际需要设定。2,2指的是2行2列共4个子图。
# ax对象是一个列表,里面是所有的axes子图。
# 如果该函数没有前2个参数来确定子图的个数,则默认只有一个子图axes。

# 该函数还有以下几个参数,分别是:
# figsize: 指定figure的宽和高,单位为英寸,总画布的大小确定了,子图的大小也就确定了。  
# dpi: 指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80 
# facecolor: 背景的颜色,默认是白色。
# edgecolor: 边框颜色,默认是黑色。
# frameon: 是否显示边框,默认是True,及显示边框

# 当然除了在plt.subplots()函数中设定各种参数,还可以通过plt.rcParams命令
# 比如
# plt.rcParams["figure.dpi"] = 500  # 设置图形的分辨率
# plt.rcParams["axes.titlesize"] = 20  # 子图标题的文字大小
# plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
# plt.rcParams['axes.unicode_minus'] = False # 使坐标轴刻度标签正常显示负号

# 具体可以参考4

# 子图与fig画布边框之间的距离调整,以及子图与子图之间的间距调整
# 一般情况下,该条命令可以不写,等实际绘制出来的图不合适的时候,再进行调整
# 该步,可以放在这里(及初始化画布和子图之后,在哪里调整都会起作用),也可以放在后面。
plt.subplots_adjust(left=?,
                    bottom=?,
                    right=?,
                    top=?,
                    wspace=?,
                    hspace=?)
# left--图形到左边缘距离;
# bottom--图形到下边缘距离;
# right--图形到右边缘距离;
# top--图形到上边缘距离;
# wspace--各子图间横向间距,及左右子图之间的距离
# hspace--各子图间纵向间距,及上下子图之间的距离

# 给总的画布fig设置标题
# 总标题也是可以有各种参数的,比如字体,大小,颜色,透明度等
# 不过一般没有特殊的要求
fig.suptitle("总标题",fontsize=50,color='black',alpha=1) 

<2>获取子图进行绘制

import matplotlib.pyplot as plt

ax1 = ax[0,0]  # 从ax集合列表中获得第一个子图,命名为ax1
ax2 = ax[0,1]  # 从ax集合列表中获得第一个子图,命名为ax2
ax3 = ax[1,0]  # 从ax集合列表中获得第一个子图,命名为ax3
ax4 = ax[1,1]  # 从ax集合列表中获得第一个子图,命名为ax4

<3>给子图设置标题

# 给子图添加标题,也可以有很多参数,比如大小,字体,颜色,透明度等
# 一般都是黑色,透明度都是1
# 颜色,color,不是colour
# 字体大小:fontsize
ax1.set_title("图1",fontsize=30,color='black',alpha=1)

<4>在子图上进行绘制

    # 当然可以绘制折线图,也可以绘制其他的图形
    ax1.plot([1,2,3], label="111")  # 这里的lable参数,其实就是对这条线进行解释的文字,后续在legend图例的时候会用到。
    ax1.plot([4,5,6], label="222") 

<5>显示图例

    # 如果在一张图中绘制多条线,为了区分,则需要显示图例。
    # 绘制图例依赖上面绘图时候的label参数
    # title: 图例也是有标题的,该参数可以写,也可以不写
    # fancybox:决定图例的方框是直角边还是圆边,如果fancybox=True,则是圆边,否则是直角边
    # loc参数决定图例的位置,
    # loc参数有'lower left','lower right','best','left','right','upper left','upper right'等选项。
    # prop参数是一个字典对象,里面包括字体,粗细,大小等参数
    ax1.legend(title='xxx',
               fancybox=False,
               loc='lower left',
               prop={'family':'SimHei','weight':'normal','size':15}) 
图例的所有位置选项如下:

image.png

<6>移除图例

    ax1.legend_.remove()  #移除子图ax1中的图例

<7>设置xy轴的名称label

    # 除了规定名称,还有别的参数,比如名字的大小,颜色,倾斜度,rotation默认是0,及是水平的
    ax1.set_xlabel("data_month",fontsize=20,color='red',rotation=0)  # rotation默认是0
    ax1.set_ylabel("员工在职人数",fontsize=20,color='red',rotation=90) # rotation默认是90

<8>网格线grid

    # 有必要的话,可以设置网格线,这样显示更加完美
    # 语法:ax1.grid(which='major',axis='x',color='gray',linestyle='-.',linewidth=1) 
    # which参数,表示对主刻度还是次刻度,还是都绘制网格线
    # axis参数决定对哪个坐标轴绘制网格线,
    # color决定网格线的颜色,
    # linestyle是网格线的形状,
    # linewidth是粗细
    # 有几个参数需要解释一下:
        # which一共3个参数['major','minor','both'],默认是major表示主刻度,
        # 后面分布为次刻度及主次刻度都显示
        # axis也有3个参数['x','y','both'],分别是对x轴,y轴,x和y轴做网格线
    ax1.grid(which='major',axis='x',color='gray',linestyle='-.',linewidth=1) 
    ax1.grid(which='major',axis='y',color='gray',linestyle='-.',linewidth=1)  
    ax1.grid(which='major',axis='both',color='gray',linestyle='-.',linewidth=1)  

<9>添加水平线和垂直线

    # ls是linestyle的缩写,c是color的缩写
    ax1.axvline(x=1,ls="-",c="red")  # 添加垂直线条
    ax1.axhline(y=1,ls="-",c="red")  # 添加水平线条

<10>添加解释性文字

    # 前2个参数代表位置,及在哪个地方写解释性文字
    # 后面的fontdict是一个字典对象,里面是一些更加细致的参数,比如颜色,大小,字体,形状,透明度等
    # 有的时候,我们不希望解释性文字太显眼,但是又不能不写,所有这个时候alpha这个参数就起到作用了。
    font = {'size':20,
            'color':'red',
            'family':'SimHei',
            'style':'italic',
            "alpha":0.3,  
            'ha':'left',
            'va':'center'}
    #ha参数是确定在水平方向的位置,有left,center,right3个选项 
    #va参数是确定在竖直方向的位置,有'top', 'bottom', 'center', 'baseline'4个选项
    
    ax1.text(1,2,"红色竖线是实施聚焦日的日期",fontdict=font)
    
    # 也可以把字段拆分,分别写,都是可以的。
    ax1.text(0.25,3,"边缘区域",fontsize=25,color='gray',ha='center',va='center',alpha=0.3)

<11>设置xy坐标轴的刻度,还可以设置精度

    # 让x轴和y轴显示所有的点
    # 有的时候,xy轴只显示几个点,其他的点回忽略
    # 这种情况,有时候会让人看起来不清楚
    # 所以,我们可以先让所有的点都显示
    # 当然,参数是一个列表,可以是真正的x,你也可以自己设置
    ax1.set_xticks(range(20),0.5)  # x轴显示所有的range(20),第二个参数是精度,可有可无。如果没有的话,就是按照实际的第一个参数来显示
    ax1.set_yticks(range(20),0.5)  # y轴显示所有的range(20),第二个参数是精度,可有可无。

    start, end = ax1.get_xlim()   # 先得到子图ax1的x轴的范围,然后重新设置x轴的刻度分布
    ax1.xaxis.set_ticks(np.arange(start, end,1))  # x轴显示的刻度,跨度是1

    start, end = ax1.get_ylim()   # 先得到子图ax1的x轴的范围,然后重新设置x轴的刻度分布
    ax1.yaxis.set_ticks(np.arange(start,end,1))  # x轴显示的刻度,跨度是1

<12>设置xy轴的范围

    ax1.set_xlim(0,50)  # 比如这里设置范围是0-50
    ax1.set_ylim(0,30)

<13>把y轴的刻度显示在左边还是右边

    ax1.yaxis.tick_left()  # 显示在左边,默认就是左边,如果采用默认的方式,则不用写该条命令
    ax1.yaxis.tick_right() # 显示在右边

<14>绘制另一个子图,每个子图的绘制方法都是一样的。

    ax2 = ax[0,1]
    ax2.plot([11,22,33],label="中国")
    ax2.plot([1,2,3],label="小日本")

<15>存储图

    plt.savefig('../data/1.png')
    plt.show()

<16>删除边框

一个axes子图是由4条边组成的,我们可以人为的决定这4条边框是否显示
删除边框有2种方法
    一个axes子图是由4条边组成的,我们可以人为的决定这4条边框是否显示
    
    #<1>方法1
    # gca即get current axes,获得当前的绘画区域,如果fig中只有一个axes,则也可以不写该条代码
    ax = plt.gca()  
    #<1> 通过set_color("none")方式删除边框
    ax1.spines["right"].set_color("none") # 右边的边去掉
    ax1.spines["top"].set_color("none")   # 上面的边去掉
    ax1.spines["left"].set_color("none")   # 上面的边去掉
    ax1.spines["bottom"].set_color("none")   # 上面的边去掉
    
    
    <2>方法2
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)

<17>移动坐标轴

    # 有的时候绘制象限图,就需要移动坐标轴
    # "data"表示按数值挪动,左边的边移动到x=0的位置
    ax1.spines["left"].set_position( ("data",0) )      
    
    # "data"表示按数值挪动,下面的边移动到y=0.05的地方
    ax1.spines["bottom"].set_position( ("data",0.05) )  

<18>清除画布

    plt.cla() # clear axes,清除axes,即当前figure中的活动的axes,但其他axes保持不变。
    plt.clf() # clear fig,清除当前figure的所有axes,但是不关闭这个fig,所以能继续复用于其他的plot。
    plt.close() # 关闭fig,如果没有指定,则指当前fig。

<19>从整个画布的角度,来控制其中的子图

# 比如,从整个画布的角度,来控制某个子图的刻度的倾斜度
plt.setp(ax1.get_xticklabels(), rotation=45) 
plt.setp(ax2.get_xticklabels(), rotation=45) 

图例

ax1.plot(xaxis, yaxis1, linewidth=3, color="red", label="intercept_driver_cnt")  
ax1.plot(xaxis, yaxis2, linewidth=3, color="blue", label="intercept_success_cnt")   

# 图例
ax1.legend(loc='upper left',fontsize=20)
即:要想用legend()函数,必须在上面绘图的时候,添加label参数

在图中每个节点标明数值

# 设置数字标签
for a, b in zip(xaxis, yaxis1): 
    ax1.text(a, b, b, ha='center', va='bottom', fontsize=15)
    

添加网格线grid

ax1.grid(True,axis='x')  
ax1.grid(True,axis='y')   

子图添加水平,垂直线

# 绘制水平线
# ax1.axhline(y = 500, color = 'red', linestyle = '-')

# 绘制垂直线
ax1.axvline(x='2023-04-24', color='blue', linestyle='-')

子图添加标题,横坐标,纵坐标

ax1.set_xlabel('Date')
ax1.set_ylabel('Number of successful interceptions')
ax1.set_title('title_1')

子图,设置坐标刻度的范围

ax1.set_ylim(0,2000)  
ax1.set_xlim(0,100)

4/plt.rcParams

plt(matplotlib.pyplot)使用rc配置文件来自定义图形的各种默认属性,称之为rc配置或rc参数。
通过rc参数可以修改默认的属性,包括窗体大小、每英寸的点数、线条宽度、颜色、样式、坐标轴、坐标和网络属性、文本、字体等。
rc参数存储在字典变量中,通过字典的方式进行访问。

image.png

5/折线图

适用场景:有一定的趋势,无论是时间趋势,还是大小趋势。
        x轴代表趋势,每个x轴刻度尺只有一个数据点
import matplotlib.pyplot as plt
import pandas as pd

data_df = pd.read_excel("../data/final.xlsx")
print(data_df.head())

# 初始化画布和子图
fig,ax= plt.subplots(2,1,figsize=(12,6),dpi=150)

# 添加主标题
plt.subplots_adjust(hspace=0.5)

# 子图1
ax1 = ax[0]
x = data_df["通勤距离"].tolist()
y1 = data_df["工作日不打车平均工时"].tolist()
y2 = data_df["工作日打车平均工时"].tolist()

ax1.plot(x,y1,label="工作日不打车时候平均工时")
ax1.plot(x,y2,label="工作日打车时候平均工时")
ax1.set_title("通勤距离_工时(20210101~20210707)",fontsize=15,color='black',alpha=1)

ax1.set_xlabel("通勤距离",fontsize=12,color='black',rotation=0)  # rotation默认是0
ax1.set_ylabel("平均工时",fontsize=12,color='black',rotation=90) # rotation默认是90

ax1.legend(loc='lower right',prop = {'family':'SimHei','weight':'normal','size':6})
ax1.grid(axis='y',color='gray',linestyle='-.',linewidth=1) 
ax1.xaxis.set_ticks(x)  # 设置x轴的刻度

# 子图2
ax2 = ax[1]
x = data_df["通勤距离"].tolist()
y = data_df["在职人数"].tolist()
ax2.plot(x,y,label="在职人数")
ax2.set_title("通勤距离_在职人数(截止到20210707)",fontsize=15,color='black',alpha=1)
ax2.set_xlabel("通勤距离",fontsize=12,color='black',rotation=0)  # rotation默认是0
ax2.set_ylabel("在职人数",fontsize=12,color='black',rotation=90) # rotation默认是90

ax2.legend(loc='lower right',prop = {'family':'SimHei','weight':'normal','size':6})
ax2.grid(axis='y',color='gray',linestyle='-.',linewidth=1)  
ax2.xaxis.set_ticks(x)  # 设置x坐标的刻度

plt.savefig("../data/房补_通勤距离_工时.pdf",dpi=150,format="pdf")   # 保存fig,dpi是分辨率,format是存储形式

plt.show()

6/散点图

适用场景:即可以看到数据的分布,也可以看到数据的大致走势。
        每个x的刻度尺可以有多个数据点。
import matplotlib.pyplot as plt 

fig,ax = plt.subplots(num="xxxx",figsize=(30,8),dpi=200) 

# 设置子区域ax的标题,同时还设置了标题的位置,set_ha是水平方向的位置,va是上下方向的位置
ax.set_title("散点图").set_ha("center")  

# 设置x轴y轴的范围,这个需要根据实际情况确定
ax.set_xlim(-3,12) 
ax.set_ylim(0,1.1) 

# 得到x轴y轴范围的最小值,最大值
xmin, xmax = ax.get_xlim() 
ymin, ymax = ax.get_ylim()

# x轴y轴显示的刻度,跨度是1
ax.xaxis.set_ticks( np.arange(xmin,xmax,1) ) 
ax.yaxis.set_ticks( np.arange(ymin,ymax,0.1) )

# 设置x轴y轴的名称
ax.set_xlabel("月份") 
ax.set_ylabel("人数")  

# 设置水平线和垂直线
ax.axhline(y=4,ls=":",c="yellow")  
ax.axvline(x=4,ls="-",c="green")   

# 添加文字
ax.text(x,y,text,fontsize=25,color="gray",ha="center",va="center",alpha=0.3)

# 绘制函数
ax.scatter(list,  # x轴
           list, # y轴
           label="xxxx",  # 图例
           c = xxx,  # 散点的颜色
           edgecolor='xxx',  # 散点边缘色,可以没有
           facecolor='xxx', # 散点填充色,可以没有
           alpha = 1,  # 散点的透明度
           s = 60 )  # 散点的大小

# 显示图例
# 注意:ax.scatter()函数中就必须有label参数,这样才能下时图例
ax.legend(title="姓名",fancybox=False,loc='lower right')  
# 参数解释:
    #title是图例的标题
    #fancybox是图例的方框是直角边还是圆边,如果fancybox=True,则是圆边,否则是直角边
    #loc就是location,就是图例的位置

7/饼状图

import pandas as pd
import nunpy as np
import matplotlib.pyplot as plt

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

# 初始化总画布和子图
fig,ax = plt.subplots(figsize=(12,6),dpi=200)
fig.suptitle("总标题_饼状图",fontsize=50,color='black',alpha=1) 

# 添加子图标题
ax.set_title('2018年8月的编程语言指数排行榜',fontsize=50,colosr='black')

# 数据
data = [0.1688,0.1496,0.0747,0.0699,0.0476,0.0354,0.0292,0.0241,0.0231,0.0140,0.3632]

# 标签
labels = ['Java','C','C++','Python','Visual Basic.NET','C#','PHP','JavaScript','SQL','Assembly langugage','其他']

#将 排列在第4位的语言(Python)分离出来
explode =[0,0,0,0.3,0,0,0,0,0,0,0]

# 使用自定义颜色
colors = ['red','pink','magenta','purple','orange']

# 将横、纵坐标轴标准化处理,保证饼图是一个正圆,否则为椭圆
ax.set_aspect('equal')

# 控制X轴和Y轴的范围(用于控制饼图的圆心、半径)
# 最后设置完圆心位置和半径大小之后,最后再把xy轴线给隐藏掉
ax.set_xlim(0,8)
ax.set_ylim(0,8)

# 不显示边框
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['bottom'].set_color('none')

# 绘制饼图
ax.pie(x=data, # 绘制数据
       labels=labels, # 添加标签
       explode=explode, # 重点突出
       colors=colors,  # 填充的颜色
       autopct='%.2f%%',  # 设置百分比的格式,保留2位小数
       pctdistance=0.8, # 设置百分比标签和圆心的距离
       labeldistance=1.0, # 设置标签到圆心的距离
       startangle=180, # 设置饼图的初始角度
       center=(4,4),  # 设置圆心的位置(相当于X轴和Y轴的范围)
       radius=3.8,  # 半径的大小(相当于X轴和Y轴的范围)
       shadow=False, # 是否有阴影,默认是没有
       counterclock= False,  #是否为逆时针方向,False表示顺时针方向
       wedgeprops= {'linewidth':1,'edgecolor':'green'},#设置饼图内外边界的属性值
       textprops= {'fontsize':12,'color':'black'},#设置文本标签的属性值
       frame=1 #是否显示饼图的圆圈,1为显示) 

# 不显示X轴、Y轴的刻度值
ax.set_xticks(())
ax.set_yticks(())

# 显示图形
plt.show()

8/柱状图

适用场景:分类的数据。
        比如某届奥运会,看看各个国家获得的奖牌的数量。
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt 

    plt.rcParams["font.family"] = ["Arial Unicode MS"]  # 规定字体
    plt.rcParams['font.sans-serif'] = ["Microsoft JhengHei"] # 显示中文 YaHei JhengHei
    plt.rcParams['axes.unicode_minus'] = False     # 正常显示负号

    # 读取数据
    data_df = pd.read_excel('/Users/houzhen/Desktop/fangjia.xlsx')

    # 对数据做必要的处理
    # 比如排序
    data_df = data_df.sort_values(by="price",ascending=True)  # 按照价格从大-->小排序

    fig,ax = plt.subplots(figsize=(12,6),dpi=144,facecolor='black',edgecolor='black')
    ax.set_title("山东省各地级市房价一览表(元/平米)").set_ha("center")

    # 在这里注意bar()函数和barh()函数的区别
    # bar()函数柱子是竖着的,barh()函数柱子是横着的
    # 把ax.barh()赋予给一个变量,这样我们通过这个变量,对柱状图进行调整,可以对其中的任何一条柱子进行调整
    x = data_df['region'].tolist() # x轴是城市
    y = data_df['price'].tolist()  # y轴是房价
    barh = ax.barh(x,y,color=np.random.rand(4) )

    barh[-1].set_color("r")  # 把最后一根柱子的颜色设置为红色

    # 给条形图添加数据标注
    for y, x in enumerate(data_df['price'].tolist()):
       ax.text(x+100, y-0.2, "%s" % x)

    # 因为这里绘制的柱子是横着的,所有可以删除所有边框
    ax.spines["right"].set_visible(False)
    ax.spines["top"].set_visible(False)
    ax.spines["bottom"].set_visible(False)
    ax.spines["left"].set_visible(False)

    ax.tick_params(labelsize=14)
    ax.set_xlabel("总价")
    ax.set_ylabel("地区")

    plt.show()

9/箱型图

箱型图的主要作用是发现数据内部整体的分布分散情况,包括上下限,各分位数,均值,异常值。
如下图所示:

image.png

基本语法
   plt.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,  设置须的属性
                manage_xticks=True, 
                autorange=False, 
                zorder=None, 
                hold=None, 
                data=None)

image.png

image.png

    基本用法:
    import pandas as pd
    import matplotlib.pyplot as plt

    # 读取数据
    data = pd.read_excel('D:\\pythondata\\learn\\matplotlib.xlsx')
    box_1, box_2, box_3, box_4 = data['收入_Jay'], data['收入_JJ'], data['收入_Jolin'], data['收入_Hannah']
	
    fig,ax = plt.subplots(figsize=(12,6),api=144)
    fig.suptitle("总标题",fontsize=50,color='black',alpha=1) 
    
    ax.set_title("xxx").set_ha("center")
    labels = 'Jay','JJ','Jolin','Hannah'#图例
    ax.boxplot([box_1, box_2, box_3, box_4],labels = labels)           
    
    plt.show()
   # pandas的dataframe绘制箱型图
   # 语法如下
   DataFrame.boxplot(column=None, 指定要进行箱型图绘制的列,默认是全部的列
                      by=None, 
                      ax=None,
                      showmeans=False, # 显示均值
                      fontsize=None, 
                      rot=0, 
                      grid=True, 
                      figsize=None, 
                      layout=None, 
                      return_type=None)
各个参数解释如下

image.png

   #例子:
   import pandas as pd
   import matplotlib.pyplot as plt

   data_df = pd.read_excel('/Users/houzhen/Desktop/fangjia.xlsx')

   fig,ax = plt.subplots(figsize=(12,6),dpi=144)
   fig.suptitle("总标题",fontsize=50,color='black',alpha=1) 
   ax.set_title("xxx").set_ha("center)

   data_df.boxplot(showmeans=True)

10/雷达图

雷达图一般用来对不同的人或事物,在多个维度进行比较.
雷达图的各个维度的取值范围一般是[0,1],所以对数据一般需要进行归一化或者标准化。

雷达图有2种方式:
   <1>绘制一张雷达图,把多个人放在一张雷达图中比较。
   <2>绘制多张雷达图,把多个人放在多张雷达图中进行比较。

比如,对如下数据绘制雷达图

image.png

image.png

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 通过plt.rcParams设置一些参数
plt.rcParams["font.family"] = ["Arial Unicode MS"]
plt.rcParams['font.sans-serif'] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False

# 读取数据
basic_df = pd.read_excel("/Users/houzhen/Desktop/111xlsx.xlsx",encoding="gb18030")

# 数据归一化
# 对每一个特征进行数据归一化
feature_name = basic_df.columns.tolist()[1:]
for each_feature in feature_name:
    max_value = basic_df[each_feature].max() # 最大值
    min_value = basic_df[each_feature].min() # 最小值
    basic_df[each_feature] = basic_df[each_feature].apply(lambda v: (v - min_value) / (max_value - min_value))

# 雷达图的各个角,分别是什么特征
feature_name = basic_df.columns.tolist()[1:]  

# 特征的个数
dataLength = len( feature_name )

# 数据
data = basic_df.values.tolist()

# 角度
angles = np.linspace(0,2*np.pi,dataLength,endpoint=False) 

# 开始绘制雷达图
# 初始化一张总画布
fig = plt.figure(figsize=(13,7))  

# 在这张画布上,添加一个子图。
# 参数polar=True,作用是创建极坐标。雷达图就需要创建极坐标
# 默认polar是False,也就是说创建的是普通的二维的直角坐标
ax = fig.add_subplot(111,polar=True) 

# 给子图添加标题,设置子图,大小等
# 当然这些参数也可以在上面设置。
ax.set_title("xxx",fontproperties="SimHei",fontsize=16)

for i in data: # 对于每个人的数据,及每一行数据
    temp_data = np.concatenate( (i[1:], [i[1:][0]]) )
    temp_angles = np.concatenate((angles,[angles[0]]))

    ax.set_thetagrids(temp_angles * 180/np.pi,feature_name,fontproperties="SimHei")
    ax.plot(temp_angles,temp_data,color=np.random.rand(4),linewidth=2,label=i[0]) 
    ax.set_rlim(0,1) # 设置半径的范围[0,1]

ax.legend(title='xxx',  # 图例的标题
          fancybox=False,  # 图例的边框是直角还是圆角
          loc='lower left',  # 图例的位置
          prop={'family':'SimHei','weight':'normal','size':15})  # 显示图例
plt.show()

11/帕累托图

帕累托(Pareto)是Excel和Tableu中非常流行的diagarm。 
在excel中,我们可以轻松地绘制帕累托图,但是我发现没有简单的方法可以在Python中绘制该图。
绘制完帕累托图之后,我们既可以知道任何一个类别的值,也可以知道哪些类别占据了总量的前xx%。
比如说,某届奥运会,我们知道每一个国家获得了多少枚金牌,同时,我们也可以知道哪些国家获得了前80%的金牌。
   import pandas as pd 
   import matplotlib.pyplot as plt
   from matplotlib.ticker import PercentFormatter

   data_df = pd.DataFrame(data={'国家':['USA', 'Canada', 'Russia', 'UK', 'Belgium', 'Mexico','Germany', 'Denmark'],'金牌数':[177.0, 7.0, 4.0, 2.0, 2.0, 1.0, 1.0, 1.0]})

   # 把金牌数降序排序
   data_df = data_df.sort_values(by='金牌数',ascending=False)
   data_df["cumpercentage"] = data_df["金牌数"].cumsum() / df["金牌数"].sum() * 100  # cumsum()函数是累加

   fig,ax = plt.subplots(figsize=(10,6),dpi=100)
   ax.set_title("帕累托图",fontproperties="SimHei",fontsize=16)
   x = data_df['国家']
   y = data_df["金牌数"]
   ax.bar(x,y,color="C0")

   #twinx()函数表示共享x轴
   #twiny()表示共享y轴
   #共享表示的就是x轴使用同一刻度线

   ax2 = ax.twinx()  # 与ax共享x轴线,twin双胞胎
   y = data_df["cumpercentage"]
   ax2.plot(x,y,color="C1",marker="D",ms=7)
   ax2.yaxis.set_major_formatter( PercentFormatter() ) # 把浮点数改为百分数

   # 最后在颜色上,做一点调整
   ax.tick_params(axis="y",colors="C0")  # tick_params()函数,从字面上理解:在刻度上调整参数
   ax2.tick_params(axis="y",colors="C1")

   plt.show()

image.png

12/表格

pandas的dataframe数据结构在呈现的时候,
会出现列名和数据错位的情况,视觉效果不是很友好。

所以如果设置为表格的话,视觉效果会大大提升。
   import pandas as pd
   import numpy as np
   import matplotlib.pyplot as plt
   import datetime
   import six
   
   # 一些参数的设置
   # 让 plt 可以正常展示中文字体
   font = {'family' : 'SimHei',
           'weight' : 'bold',
           'size'  : '16'}
   plt.rc('font', **font) 
   plt.rc('axes', unicode_minus=False) 

   # 绘制表格
   # 设置单元格的宽,高,及列的宽度,行的高度,根据实际情况确定
   # 然后根据宽度和高度,自适应设置画布的大小
   col_width, row_height = (5.0, 0.8) 
  
   size = (np.array(data.shape[::-1]) + np.array([0, 1])) * np.array([col_width, row_height])
   
   # 初始化画布fig和绘制区域ax
   fig, ax = plt.subplots(figsize=size,dpi=150)
   # 这里是关闭axes的axis,及关闭坐标轴,只留有axex,因为我们要做的是绘制表格,而不是坐标轴,
   ax.axis('off') 
   
   # 使用axes的table()函数绘制表格
   plt_table = ax.table(cellText=data.values,  # 数据
                        bbox=[0, 0, 1, 1], 
                        colLabels=data.columns, # 字段名称
                        cellLoc='center') # 类似于excel的居左,居中,居右,left,center,right
   
   # 整个画布的标题,因为该fig只有一个ax,所以一般来讲,fig的标题就是ax的标题
   plt.title('【巨像文明】不删档测试机器人报数测试_',size = '20')

   # 函数中的两个数值参数对应备注展示的位置,对应x轴和y轴,默认(0,0)在左下角
   # 添加注释,及辅助阅读本数据的人
   # 注释可以单独设置字体的参数,因为
   plt.text(0,-0.15,
            "备注:截止日期:"+" 23:59:59。",
            fontdict={'color': '#8E8E8E',
                      'size': '20',
                      'style': 'italic'})

   # 设置表格字体
   plt_table.auto_set_font_size(False) # 关闭自动设置字体的大小
   plt_table.set_fontsize(20) # 设置字体的大小
   
   # 锦上添花
   # 设置表头颜色和间隔颜色

   row_colors = ['#f1f1f2', 'white'] # 间隔色
   edge_color = 'black' # 表格线
   header_color='steelblue' # 表头色

   for k, cell in  six.iteritems(plt_table._cells):
       text = cell._text.get_text()
       
       # 设置表格线
       cell.set_edgecolor(edge_color)
       cell.set_text_props(ha='center')
       if k[0] == 0: # k[0] == 0,代表这是表头
           # 设置表头色
           cell.set_text_props(weight='bold',color='white')
           cell.set_facecolor(header_color)
           
       elif k[0] % 2 == 0: # 如果不是表头,且行号是2的倍数,则是一种颜色
           # 设置间隔色if k[0] % 2 == 0:
           cell.set_facecolor(row_colors[0])
           
       else: # 如果不是表头,且不能被2整除,则是另一种颜色
           cell.set_facecolor(row_colors[1])
   

python matplotlib,我不初始化fig对象,而是直接采用plt绘制图,可以吗

是可以的。
你可以在不显式初始化`Figure``fig`)对象的情况下,直接使用`matplotlib.pyplot`(通常缩写为`plt`)来绘制图形。
`matplotlib.pyplot`模块提供了一个类似于MATLAB的绘图系统接口,它会自动管理图形和坐标轴(axes)的创建,使得绘图过程更加简便快捷。

当你调用`plt.plot()``plt.scatter()`等绘图函数时,如果当前没有活动的图形(figure)或坐标轴(axes),`matplotlib.pyplot`会自动为你创建一个新的图形和坐标轴来承载你的绘图数据。

下面是一个简单的例子,展示了如何在不显式初始化`Figure`对象的情况下,使用`plt`来绘制一个线图:
import matplotlib.pyplot as plt  
 
# 直接绘制线图  
plt.plot([1, 2, 3], [4, 3, 2])  
 
# 添加标题和轴标签  
plt.title('Simple Plot')  
plt.xlabel('x axis')  
plt.ylabel('y axis')  
 
# 显示网格(可选)  
plt.grid(True)  
 
# 显示图表  
plt.show()

在这个例子中,我们没有创建任何`Figure``Axes`对象,但仍然能够成功地绘制出一个线图,并添加了标题、轴标签和网格。`plt.show()`函数负责在屏幕上显示这个图形。

然而,当你需要对图形进行更复杂的布局控制(比如创建子图、调整坐标轴位置等)时,使用`matplotlib`的面向对象接口(即显式创建`Figure``Axes`对象)可能会更加灵活和强大。
但在简单的绘图任务中,`matplotlib.pyplot`提供的便捷接口已经足够使用了。

plt和fig之间,有什么关系

`matplotlib`库中,`plt`(通常是`matplotlib.pyplot`的别名)和`fig`(代表`Figure`对象)之间的关系可以概括为:`plt`提供了一套面向过程的函数接口,用于创建和管理图形(`Figure`)及其上的各种元素(如坐标轴`Axes`、图例`Legend`、标题`Title`等),而`Figure`对象则是这些图形元素在内存中的具体表示。

当你使用`plt`的函数(如`plt.plot()``plt.scatter()`等)进行绘图时,如果当前没有活动的`Figure`对象,`plt`会自动为你创建一个新的`Figure`对象,并在其上创建一个或多个`Axes`对象(默认情况下是一个)。然后,绘图函数会将数据绘制到这些`Axes`对象上。

如果你需要更直接地控制图形的创建和管理,你可以使用`matplotlib`的面向对象接口,即显式地创建`Figure``Axes`对象。
这样,你就可以更灵活地控制图形的布局和样式。然而,在大多数情况下,使用`plt`提供的函数接口已经足够方便和强大。

以下是一个简单的例子,展示了使用`plt`和显式创建`Figure`对象之间的区别:
import matplotlib.pyplot as plt  
  
plt.plot([1, 2, 3], [4, 3, 2])  
plt.title('Plot using plt')  

plt.show()

在这个例子中,`plt`自动为你创建了一个`Figure`对象和一个`Axes`对象,并将数据绘制在`Axes`上。
import matplotlib.pyplot as plt  
  
# 显式创建Figure对象  
fig = plt.figure()  
# 在Figure上显式创建Axes对象  
ax = fig.add_subplot(111)  # 这里的111表示1行1列的第1个位置  
ax.plot([1, 2, 3], [4, 3, 2])  
ax.set_title('Plot using Figure and Axes')  

plt.show()

 在这个例子中,我们首先使用`plt.figure()`创建了一个`Figure`对象,然后使用`fig.add_subplot()``Figure`上创建了一个`Axes`对象,并通过`ax``Axes`对象的引用)来绘制数据和设置标题。虽然这种方法更加灵活,但在简单的绘图任务中,使用`plt`提供的函数接口通常更为方便。
 
 

针对matplotlib,如果我先初始化了一个fig对象,然后我再使用plt来绘制图形,那么是不是我所绘制的所有的元素都是在fig对象上绘制的呢

在matplotlib中,确实可以通过先初始化一个`Figure`对象(通常简称为`fig`),
然后在这个`Figure`对象上添加各种元素(如轴`Axes`,图形`plot`,图例`legend`等)来绘制图形。

然而,当你提到使用`plt`(即`matplotlib.pyplot`的常用缩写)来绘制图形时,情况略有不同,但基本上你的理解是正确的。

`matplotlib.pyplot`是一个面向绘图的模块,它提供了一个类似于MATLAB的绘图系统。
当你使用`plt`函数(如`plt.plot()`, `plt.scatter()`, `plt.hist()`等)时,matplotlib实际上会在内部为你管理一个或多个`Figure``Axes`对象。
如果在你调用`plt`绘图函数之前没有显式地创建并指定一个`Figure`对象,matplotlib会自动为你创建一个新的`Figure``Axes`。

但是,如果你已经创建了一个`Figure`对象(比如`fig = plt.figure()`),并且你希望在这个特定的`Figure`对象上绘图,你需要先获取或创建一个`Axes`对象(通过`fig.add_subplot()`, `fig.add_axes()`等方法),然后使用这个`Axes`对象来绘制图形,而不是直接使用`plt`的函数。这是因为直接使用`plt`的函数(如`plt.plot()`)默认是在当前激活的`Axes`上绘图,而当前激活的`Axes`可能不是你之前创建的`Figure`对象上的`Axes`。

然而,有一个例外是,如果你已经通过`plt.figure()`创建了一个`Figure`,并且没有切换到其他`Figure`,那么接下来直接使用`plt`的绘图函数(如`plt.plot()`)实际上是在这个`Figure`上绘制图形,因为matplotlib默认会将最近创建的`Figure`设置为当前`Figure`。
但是,为了代码的清晰和可维护性,建议明确地使用`Figure``Axes`对象来管理你的绘图。

总结来说,虽然直接使用`plt`的绘图函数在大多数情况下会在你期望的`Figure`上绘制图形(如果你没有创建多个`Figure`或没有明确切换到其他`Figure`),但最佳实践是显式地管理`Figure``Axes`对象,以确保绘图操作的精确控制。