美文网首页
Matplotlib & Numpy

Matplotlib & Numpy

作者: hyfine | 来源:发表于2017-11-22 23:55 被阅读0次

    注:本教程内容整理自b站视频,部分原教程来自麦子学院,部分来源于网络


    Matplotlib初步应用

    环境搭建

    采用anaconda,自带各种科学计算的库,省去自己安装,版本适配的麻烦


    Numpy

    Numpy是一种开源的扩展的数值计算库。

    • ndarray,numpy的array对象。三种方法获得该对象:
      • nd_a = np.array(py_a) # python的数组a通过numpy.array方法转变为ndarray类型的数组
      • nd_b = np.arange(10) # arange函数生成ndarray对象
      • 读取数据库或文件:nd_c = np.loadtxt(parameters),注意参数的作用。
    • 索引和切片
      • ndarray和array一样,从0元素开始索引
      • 用name[start :end :step]方式切片
    • numpy常用函数
      • min、max、median、mean(平均值)、var(方差)、sort

      • 函数的调用支持面向过程和面向对象两种方式,np.sort(ndarrayObj)和ndarrayObj.sort()效果一样,这里注意一个区别。

      • np.sort(ndarray)不会改变ndarray原数组对象,返回一个新的已排序的对象,而ndarray.sort()不会产生新对象,而是将自身排序。

      • random随机数生成、linspace(start,end,amount)生成等区间的离散列。

      • random.randn(count)生成count个均值为0方差为1的数组

      • 数据的导入:converters参数的使用。

        # 这里将第0列日期数据的str型数据转换成float,且日期数据格式为‘12/01/1995’(1995-12-01)
        # 需要导入包
        import matplotlib.datas as matdata
        date,otherdata = np.loadtxt(..,converters={0:matdata.strpdata2num('%m/%d/%y')},..)
        # 显示的时候如果需要这个日期数据,用相应的画图函数
        plt.plot_date(date,otherdata)
        # 这个函数会识别float形式的日期数据
        
        # 生成数据
        #创造一组服从正态分布的定量数据
        data = normal(0, 10, size=10)
        #创造一组服从均匀分布的定性数据
        data = randint(0, 10, size=10)
        
      • numpy统计函数:

        • 位置:均值mean(ndarray)、中位数median(ndarray)、众数mode(ndarray)

        • 发散程度:极差ptp(data)、方差var(ndarray)、标准差std(ndarray)

        • 异常(偏差程度,z-分数):(data[0]-mean(data)) / std(data),通常绝对值大于3视为异常

        • 相关度(协方差COV、相关系数衡量CORRCOEF):

          img
          #计算两组数的协方差
          #参数bias=1表示结果需要除以N,否则只计算了分子部分
          #返回结果为矩阵,第i行第j列的数据表示第i组数与第j组数的协方差。对角线为方差
          cov(data, bias=1)
          
          #计算两组数的相关系数
          #返回结果矩阵,第i行第j列的数据表示第i组数与第j组数的相关系数。对角线为1
          corrcoef(data)
          
      | 包            | 方法       | 说明             |
      | ------------ | -------- | -------------- |
      | numpy        | array    | 创造一组数          |
      | numpy.random | normal   | 创造一组服从正态分布的定量数 |
      | numpy.random | randint  | 创造一组服从均匀分布的定性数 |
      | numpy        | mean     | 计算均值           |
      | numpy        | median   | 计算中位数          |
      | scipy.stats  | mode     | 计算众数           |
      | numpy        | ptp      | 计算极差           |
      | numpy        | var      | 计算方差           |
      | numpy        | std      | 计算标准差          |
      | numpy        | cov      | 计算协方差          |
      | numpy        | corrcoef | 计算相关系数         |
    

    练习一:numpy生成100以内随机数组,存储数组到文件,读取文件,数组排序、求最大值、最小值、均值、方差

    import  numpy as np
    # 产生100个元素的ndarray,[0,1000)之间
    nd_a = np.random.randint(0,1000,100)
    
    # 保存为文件,参数看文档
    np.savetxt('arraydata.txt',nd_a,delimiter=',',header='my random data',footer='over',fmt='%d')
    
    # 读取文件
    nd_b = np.loadtxt('arraydata.txt',dtype=int,delimiter=',',skiprows=1,unpack=False,)
    
    # 对比原数组和读取的数组元素个数是否一致
    print('loaded-' + str(nd_b.size) + ',original-'+str(nd_a.__len__()))
    
    # 排序
    nd_c = np.sort(nd_b)
    
    # 输出排序后的结果:排序产生的新数组和原数组
    print(nd_c)
    print(nd_b)
    
    # 输出max
    print('max:loaded-'+ str(np.max(nd_b)) + ',original-' + str(nd_a.max()))
    # 输出min
    print('min:loaded-'+ str(np.min(nd_b)) + ',original-' + str(nd_a.min()))
    # 输出mean
    print('mean:loaded-'+ str(np.mean(nd_b)) + ',original-' + str(nd_a.mean()))
    #输出方差var
    print('avriance:loaded-'+ str(np.var(nd_b)) + ',original-' + str(nd_a.var()))
    

    练习二:Iris数据集的简单练习

    import  numpy as np
    # 这里的路径是因为本py文件和数据文件不在一个目录下
    import  os
    pro_root = os.path.abspath('..')
    sepal_length,sepal_width,petal_length,petal_width = np.loadtxt(pro_root+'\\dataset\\iris.data',
                      delimiter=',',
                      unpack=True,dtype=float,usecols=(0,1,2,3))
    
    # 三种花的统计值,简单的统计
    print(sepal_length[:50].mean())
    print(sepal_length[:50].var())
    
    print(sepal_length[51:100].mean())
    print(sepal_length[51:100].var())
    
    print(sepal_length[101:150].mean())
    print(sepal_length[101:150].var())
    
    #---------------------numpy简单学习--------------------------------
    
    # 列表list转矩阵
    array = np.array([[1,2,3],[2,3,4]]) # 2*3矩阵
    
    # 查看维度
    array.ndim # dimention
    
    # 形状,行列值
    array.shape
    
    # 大小,个数
    array.size
    
    # 指定array类型
    x = np.array(list,dtype=np.xxx) # np.xxx表示np的类型
    x.dtype # 查看类型
    
    # 生成指定维度的空array
    x = np.zeros((2,3,4)) # 这表明x是三维数组,2行3列,第三个维度size(深度、高度)为4
    
    # 同理生成值都为1的array
    x = np.ones((2,3,4))   # 同理,np.empty((shape)) 生成近似zeros的array
    
    # 产生随机的矩阵
    x = np.random.random((shape)) # 生成shape样式的矩阵,值随机(0,1)区间内
    
    # 生成有序的序列
    x = np.arange(start,end,step)  # 生成1维数据列,类似python的range的效果,默认区间左闭右开
    # 注,range返回的是range对象,到list还需要转换
    
    # 将np.array重新构形
    x.reshape((new shape)) # 比如 new shape = (2,3,4) 将x装换为3维矩阵
    # 注,转换前后的size不能变,如size=10的array不能reshape为(2,3,4)的矩阵
    
    x.reshape((-1,3,4)) # new shape中可以用-1表示自动计算值,根据size自动填写,显然只能指定一个-1值
    
    # 区间均分,类似于分箱
    x = np.linspace(start,end,nbins) # 将[start,end]区域分成nbins段,返回一个array,默认包含首尾(闭区间)
    
    
    # -------------- 基础运算 -------------------------------
    # np中的运算会作用于array的每个元素,可以直接调用np的函数,也可以用oob方式调用ndarray的成员方法,且可以指定参数axis,表示对某一维度上进行运算
    
    # 矩阵乘法 np.dot(x,y)
    x = np.arange(0,4).reshape((2,2))
    y = np.arange(5,9).reshape((-1,2))
    r1 = x*y         # 元素对应相乘
    r2 = np.dot(x,y) # 矩阵乘法运算
    r2 = x.dot(b)    # 同上
    
    # 最大,最小,求和,一下方法可指定参数axis(如,axis=0),表示在这个维度、轴、rank上运算
    np.sum(x) # x.sum()
    np.min(x) # x.min()
    np.max(x) # x.max()
    
    # 最大值最小值的索引,多维矩阵也按一维线性索引返回
    index = np.argmin(x)
    index = np.ragmax(x)
    
    # 中位数、平均值、累计值
    mean = np.mean(x)
    median = np.median(x)
    cumsum = np.cumsum(x) # 累计和
    np.diff(x) # x[j,i+1]-x[j,i],按行输出
    
    np.sort(x) # 逐行排序
    
    # 矩阵转置
    np.transpose(x) 
    x.T
    
    # clip可以理解为一种过滤
    np.clip(x,a,b) # x矩阵的元素中所有小于a的元素置为a,大于b的置为b,即ab为取值范围
    
    # 多维矩阵的单行形式
    x.flat # x.flatten() ,当然也可以reshape到一维数组
    
    # 数据合并
    np.vstack((a,b)) # vertical 垂直合并
    np.hstack((a,b)) # horizontal 水平合并a、b
    np.concatenate((a,b,c,d,...,n),axis=j) # 在j维度上对a到n的array合并
    
    # 分裂矩阵
    np.split(x,nbins,axis=n) # 对x做第n维的nbins等份分割,检测nbins必须满足axis=n上等份要求,否则出错,如4列分3份,出错……
    np.array_split(x,nbins,axis=n) # 不等份 分割。对nbins无检测
    
    ##! python默认是引用赋值
    a = np.array(....)
    b = a # 此时a is b == True,同一块内存,修改一个,都改变
    b = a.copy() # 重新创建一个值一样的对象给b,此时a、b两个不同内存空间的对象,不再关联,彼此独立
    

    散点图

    scatter(xList,yList)函数

    外观参数:用以区分不同类型数据。颜色-c,点大小-s,透明度-alpha,点形状-marker

    # 查看花的sepal的length和width的关系
    import  numpy as np
    import  matplotlib.pyplot as plt
    import  os
    pro_root = os.path.abspath('..')
    
    sepal_length,sepal_width = np.loadtxt(pro_root+'\\dataset\\iris.data',
                      delimiter=',',
                      unpack=True,dtype=float,usecols=(0,1))
    
    plt.scatter(sepal_width[:50],sepal_length[:50],marker='*',c='red',alpha=0.5,s=50)
    plt.scatter(sepal_width[51:100],sepal_length[51:100],marker=',',c='green',alpha=0.5,s=50)
    plt.scatter(sepal_width[101:150],sepal_length[101:150],marker='.',c='blue',alpha=0.5,s=50)
    plt.show()
    
    # 可以看到三种花的sepal的宽和长都是近似正相关的
    

    折线图

    plt.plot(xlist,ylist)、plt.plot_date(date,data,linestyle='.')(这个函数需要指定linestyle,否则画出的是点,而不是线)

    练习一:[0,10]内的正弦图象

    # 0,10内正弦图象
    import  numpy as np
    import  matplotlib.pyplot as plt
    
    # 只分成20份,能看到折线
    xlist = np.linspace(0,10,20)
    ylist = np.sin(xlist)
    plt.plot(xlist,ylist,'b:')
    
    # 分成100份,几乎是光滑曲线
    alist = np.linspace(0,10,100)
    blist = np.cos(alist)
    plt.plot(alist,blist,'r--')
    
    plt.show()
    
    # plot函数的参数需要注意,'r--'这是一种组合的参数,r表示颜色red,--表示线的样式,具体的组合看文档
    

    练习二:iris练习

    import  numpy as np
    import  matplotlib.pyplot as plt
    import  os
    pro_root = os.path.abspath('..')
    data = np.loadtxt(pro_root+'\\dataset\\iris.data',
                      delimiter=',',
                      unpack=False,dtype=float,usecols=(0,1,2,3))
    
    for x in data[0:50]:
        plt.plot(x,'r--')
    for x in data[51:100]:
        plt.plot(x,'g-')
    for x in data[100:150]:
        plt.plot(x,'b-.')
    
    # 对图做个加工
    # x、y轴标签与图形标题
    plt.xlabel('category')
    plt.ylabel('value')
    plt.title('iris\'s sepal and petal leagth and width')
    
    # X轴上的标签
    xticks=['sepal length','sepal width','petal length','petal width']
    #设置x轴的刻度,将构建的xticks代入
    plt.xticks(range(len(xticks)),xticks,rotation=0)
    
    # 图中可以看出三种类型的折线图
    plt.show()
    
    

    条形图

    np.bar(parameters)

    练习:iris的两种条形图

    """
    累计条形图,stacked bar graph
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from src.utils import utils as tool
    
    sepal_length,sepal_width,petal_length,petal_width = np.loadtxt(tool.getPath()+'/dataset/iris.data',
                      delimiter=',',
                      unpack=True,dtype=float,usecols=(0,1,2,3))
    
    # data
    sun_sepal_length = [np.sum(sepal_length[0:50]),np.sum(sepal_length[51:100]),np.sum(sepal_length[101:150])]
    sun_sepal_width = [np.sum(sepal_width[0:50]),np.sum(sepal_width[51:100]),np.sum(sepal_width[101:150])]
    sun_petal_length = [np.sum(petal_length[0:50]),np.sum(petal_length[51:100]),np.sum(petal_length[101:150])]
    sun_petal_width = [np.sum(petal_width[0:50]),np.sum(petal_width[51:100]),np.sum(petal_width[101:150])]
    
    
    # plot
    left = np.arange(3)
    width = 0.5
    # 这里有大量重复的矩阵计算,需要优化
    bar1 = plt.bar(left,sun_sepal_length,width,yerr=sun_sepal_length,align='center',color='red')
    bar2 = plt.bar(left,sun_sepal_width,width,yerr=sun_sepal_width,bottom=sun_sepal_length,align='center',color='green')
    bar3 = plt.bar(left,sun_petal_length,width,yerr=sun_petal_length,bottom=np.add(sun_sepal_length,sun_sepal_width),align='center',color='blue')
    bar4 = plt.bar(left,sun_petal_width,width,yerr=sun_petal_width,bottom=np.add(np.add(sun_sepal_length,sun_sepal_width),sun_petal_length),align='center',color='black')
    # 坐标轴美化
    plt.ylabel('value')
    plt.title('this is title')
    plt.xticks(left,('typeA','typeB','typeC'))
    # 图例标注
    plt.legend((bar1[0], bar2[0],bar3[0],bar4[0]), ('sepal_length', 'sepal_width','petal_length','petal_width'))
    plt.show()
    
    """
    并列对比条形图
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from src.utils import utils as tool
    
    sepal_length,sepal_width,petal_length,petal_width = np.loadtxt(tool.getPath()+'/dataset/iris.data',
                      delimiter=',',
                      unpack=True,dtype=float,usecols=(0,1,2,3))
    
    # data
    sun_sepal_length = [np.sum(sepal_length[0:50]),np.sum(sepal_length[51:100]),np.sum(sepal_length[101:150])]
    sun_sepal_width = [np.sum(sepal_width[0:50]),np.sum(sepal_width[51:100]),np.sum(sepal_width[101:150])]
    sun_petal_length = [np.sum(petal_length[0:50]),np.sum(petal_length[51:100]),np.sum(petal_length[101:150])]
    sun_petal_width = [np.sum(petal_width[0:50]),np.sum(petal_width[51:100]),np.sum(petal_width[101:150])]
    
    x = np.arange(0,15,5)
    width = 0.5
    
    bar1 = plt.bar(x,sun_sepal_length,width,color='red')
    bar2 = plt.bar(x+width+0.1,sun_sepal_width,width,color='green')
    bar3 = plt.bar(x+width*2+0.2,sun_petal_length,width,color='blue')
    bar4 = plt.bar(x+width*3+0.3,sun_petal_width,width,color='black')
    
    plt.xticks(x+width*2,('A','B','C'))
    plt.legend((bar1[0],bar2[0],bar3[0],bar4[0]),('sepal_length','sepal_width','petal_length','petal_width'),loc=2)
    
    plt.show()
    

    直方图

    类似于条形图,但是通常是展示连续数据。

    plt.hist(data,bins,color,normed),bins表示的直方图的分段数量,normed决定y轴是频率还是计数

    # 随机生成数据做直方图
    import numpy as np
    import matplotlib.pyplot as plt
    
    mean = 20
    var = 0.5
    data = mean+var*np.random.randn(100000)
    
    # plt.hist(data,bins=50,normed=False,color='red')
    # 当直方图的划分很大时,就是密度曲线
    plt.hist(data,bins=500,normed=True,color='red')
    plt.show()
    
    # 二维的直方图,用颜色表示联合密度
    import numpy as np
    import matplotlib.pyplot as plt
    
    # xy均值分别为1和5,方差都为1
    x = 1+np.random.randn(2000)
    y = 5+np.random.randn(2000)
    
    plt.hist2d(x,y,bins=40)
    # 图通过颜色深浅表示概率,显然在(x,y)=(1,5)处密度最大,颜色最亮
    plt.show()
    

    饼状图

    plt.pie(dataArray,labels,autopct='%d',explode,shadow)

    • autopct用于格式化饼块的占比数据显示格式
    • explode是一个集合,表示每一块饼距离中心的距离,用以强调突出某一个饼块
    • shadow是boolean型数据指示是否给饼块添加立体阴影
    import matplotlib.pyplot as plt
    
    data = (20, 10, 30, 25)
    labels = 'SH', 'BJ', 'SZ', 'GZ'
    colors = ('red', 'green', 'blue', 'yellow')
    explode = (0, 0, 0.2, 0.05)
    
    # 饼图中坐标x、y默认不是1比1的,所以图像会椭圆,需要指定坐标轴1:1以画出正圆
    plt.axes(aspect=1)
    
    plt.pie(x=data,labels=labels,colors=colors,explode=explode, autopct='%0.1f%%', shadow=True)
    plt.show()
    
    

    箱形图

    plt.boxplot(data,sym,whis)

    • sym表示异常点的显示样式,可同时指定颜色、样式等
    • whis,whiskers,表示离群点的范围。箱形图会统计[最小值、四分位值Q1、中间值、四分之三分位值Q3、最大值,平均值,以及离群点],这里最小值和最大值是排除离群点的,那么怎么确定离群点和最小值最大值之间的区分呢?用whis,$最小值=Q1-(Q3-Q1)whis$,$最大值=Q3+(Q3-Q1)whis$,即异常点的判定取决于箱长(Q3-Q1)和whis。whis默认为1.5
    import numpy as np
    import matplotlib.pyplot as plt
    from src.utils import utils as tool
    
    sepal_length,sepal_width,petal_length,petal_width = np.loadtxt(tool.getPath()+'/dataset/iris.data',
                      delimiter=',',
                      unpack=True,dtype=float,usecols=(0,1,2,3))
    
    # 画三种花的sepal_length的箱形图
    x = sepal_length[:50],sepal_length[51:100],sepal_length[101:150]
    labels = 'A','B','C'
    
    plt.boxplot(x,labels=labels,whis=1,sym='bx')
    plt.show()
    
    # test whis
    import matplotlib.pyplot as plt
    
    x = range(1,100,1)
    # Q1=25 MID=50 Q3=75 boxLength=50, 如果whiskers=0.4,则上下都会有5个离群点
    plt.boxplot(x,whis=0.4,sym='r.')
    plt.show()
    

    颜色和样式

    调整颜色、线型、点型

    • 字符表示八种内建颜色:red、green、blue、cyan、magenta、yellow、black、white,均可用首字母替代。还可以十六进制表示颜色,如#FF08AB,分别表示三个颜色通道值。还可以RGB元组表示,如(255,255,255)。还有一种灰度表示,color=‘0.5’,表示图像是一个灰色图像,值表示颜色程度。
    • 点,直接在matplotlib的官网文档中找markers。matplotlib默认在显示不同marker时分配不同颜色(认为是不同的需要显示的对象)。
    • 线:‘--‘虚线,’-‘实线,’-.‘点划线,’:‘点线。
    • 样式字符串:可同时在字符串中包含以上三种样式信息,如'rx--',表示红色,点为x,线为虚线

    编程方式

    pyplot、pylab和面向对象的方式

    • pyplot:简单易用,底层定制能力不够。
    • pylab:结合matplotlib和numpy的模块,模拟了matlab的环境,不推荐用了
    • 面向对象:matplotlib的精髓,更基础和底层的方式。

    推荐13两种方式根据实际情况综合使用


    子图subplot

    matplotlib绘图的三个层级:FigureCanvas 画布,Figure 图,Axes 坐标系。一张图上画多个对比图像,这其实不是多个Figure,而是一个Figure上建立多个Axes,每个Axes表达一个内容。

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(1,10)
    
    fig = plt.figure()
    
    axe1 = fig.add_subplot(221)
    axe2 = fig.add_subplot(222)
    axe3 = fig.add_subplot(223)
    axe4 = fig.add_subplot(224)
    
    axe1.plot(x,[ i**3 for i in x])
    axe2.scatter(x,x)
    axe3.hist(x,bins=9)
    axe4.plot(x,-x)
    
    plt.show()
    #--------------另一种方式----------------
    fig, axes = plt.subplots(ncol=2,nrow=2)
    ax1,ax2,ax3,ax4 = axes.ravel()
    # 再用每个ax再每个图轴上画数据
    

    多图

    import matplotlib.pyplot as plt
    
    f1 = plt.figure()
    ax1 = f1.add_subplot(111)
    ax1.plot([1,2],[1,2])
    
    f2 = plt.figure()
    ax2 = f2.add_subplot(222)
    ax2.plot([1,2],[2,1])
    
    # 一次弹出两个图框
    plt.show()
    

    网格

    axe.grid()、plt.grid()

    图例

    画图的时候指定label,然后plt.legend()自动根据label显示图例

    图例可以由plt显示,也可以由axe显示。同样label可以在不同的时机创建

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(10)
    f = plt.figure()
    ax = f.add_subplot(111)
    ax.plot(x,x,label='$ y = x $',color='b')
    ax.plot(x,x**2,label='$ y = x^2 $',color='g')
    ax.plot(x,x**3,label='$ y = x^3 $',color='r')
    
    ax.grid(linestyle='-.',color='y')
    
    ax.legend()
    
    # 调整坐标轴范围(x1,x2,y1,y2)
    plt.axis([0,10,0,500])
    

    坐标轴范围

    plt.axis([x1,x2,y1,y2])
    plt.xlim()
    plt.ylim()
    
    

    坐标轴刻度

    ax = plt.gca() # get current axe,获取当前的坐标轴
    ax.locator_params(nbins=10) # nbins表示需要将轴刻度分成几个格子,可以通过'x'/'y'制定某一个坐标轴
    

    日期作为轴刻度

    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import numpy as np
    
    # 导入时间模块
    import datetime
    
    # 创建两个时间对象
    start = datetime.datetime(2015,11,6)
    stop = datetime.datetime(2017,11,6)
    # 创建时间间隔对象
    delta = datetime.timedelta(days=1)
    # 创建时间格式化器
    date_format = mpl.dates.DateFormatter('%Y-%m-%d')
    
    # 转换成matplotlib的时间序列对象
    dates = mpl.dates.drange(start,stop,delta)
    
    # 生成随机数据
    y = np.random.randn(len(dates))
    
    ax = plt.gca()
    # 画时间折线图,实线,不给marker(不会突出数据点)
    ax.plot_date(dates,y,linestyle='-',marker='')
    # 将日期格式化对象应用到x轴上
    ax.xaxis.set_major_formatter(date_format)
    
    # 调整x轴日期标签自适应显示
    plt.gcf().autofmt_xdate()
    
    plt.show()
    

    添加坐标轴

    效果:多重y轴,同一个axe中的两个线采用不用的刻度,这个时候需要两条对应的坐标轴,左右并列分别对应两条数据线。

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(0,11)
    
    y1 = x**2
    y2 = -3*x+3
    
    plt.plot(x,y1,color='r',label='$y1=x^2$')
    
    # 添加一条并列坐标轴
    plt.twinx()
    plt.plot(x,y2,color='b',label='$y2=-3*x+3$')
    
    # 此时两条线y1 y2就在同一个axe上对应不同的y轴
    plt.legend()
    plt.show()
    
    #-----------------OOP方式--------------------------
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(0,11)
    
    y1 = x**2
    y2 = -3*x+3
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    l1, = ax.plot(x,y1,color='r',label='$y1=x^2$')
    
    ax2 = ax.twinx()
    l2, = ax2.plot(x,y2,color='b',label='$y2=-3*x+3$')
    
    # 这里需要了解axe和figure的范围,若gcf()再legend,图例会滑到整个图的四个角,坐标轴外面
    # 若gca()表示获取到轴,再legend,图例画在轴范围内
    plt.gca().legend((l1,l2),('A','B'),loc=0)
    plt.show()
    
    #---------------------
    # 同理,twiny可以获得并列的x轴共用一个y轴
    

    注释

    key word:annotate

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(-10,11)
    y = x**2
    
    plt.plot(x,y,'b-')
    
    # xy表示箭头的位置,xytext表示注释文本的坐标
    # arrowprops字典类型的关于箭头的属性设置。
    # facecolor颜色,frac箭头百分百,arrowstyle是一个内置样式,查看文档具体的props设置
    plt.annotate('this is bottom',xy=(0,1),xytext=(-3,20),
                 arrowprops={'arrowstyle':'->'})
    
    plt.show()
    
    

    画文字

    plt.text(x,y,words),words文字内容自动识别Latex形式的字符串

    Latex学习链接

    注:因为latex中有大量的反斜杠,推荐用r'........'的形式创建字符串,表示默认不转义反斜杠

    区域填充

    区域上色

    key words: fill() fill_between()

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0,5*np.pi,1000)
    
    y1 = np.sin(x)
    y2 = np.cos(x)
    '''
    
    plt.fill(x,y1,'b',alpha=0.3)
    plt.fill(x,y2,'r',alpha=0.3)
    
    '''
    # 交集填充,where表示填充区域的条件表达式
    # interpolate表示是否完全填充,因为数据点是离散的,粒度太粗的时候,会有区域填充不到,这个参数会实现完全填充
    plt.fill_between(x,y1,y2,where=(y1>y2),facecolor='r',alpha=0.5,interpolate=True)
    plt.fill_between(x,y1,y2,where=(y1<y2),facecolor='b',alpha=0.5)
    
    plt.show()
    
    

    形状

    key words: matplotlib.patches add_patch

    import matplotlib.pyplot as plt
    import matplotlib.patches as mp
    
    # 构建一个圆对象,xy是圆心位置
    circle = mp.Circle(xy=(1,2),radius=1,
                       color='blue',alpha=0.5,fill=True,ls='-.')
    
    # 矩形,xy是左下角坐标
    rect = mp.Rectangle(xy=(3,3),width=2,height=1,color='g',ls='-',alpha=0.5)
    
    # 多边形
    rp = mp.RegularPolygon(xy=(5,5),numVertices=7,radius=1,alpha=0.3,color='r')
    
    # 椭圆
    elp = mp.Ellipse(xy=(1,4),width=3,height=1,color='y',alpha=0.3)
    
    ax = plt.gca()
    # 该图轴上添加这个图块,传入图块对象
    ax.add_patch(circle)
    ax.add_patch(rect)
    ax.add_patch(rp)
    ax.add_patch(elp)
    
    # 设置轴范围
    # ax.set_xlim(0,10)
    # ax.set_ylim(0,10)
    
    # 设置坐标轴相等,xy比例相同
    plt.axis('equal')
    plt.show()
    

    美化-样式

    使用多种画图样式

    key words:plt.style plt.style.use('xx') plt.style.available

    极坐标

    import matplotlib.pyplot as plt
    import numpy as np
    
    r = np.arange(1,6,1)
    theta = np.arange(0,2*np.pi+1,np.pi/2)
    
    # projection透射,表示轴的投射方式,这里采用极坐标polar
    ax = plt.subplot(111,projection='polar')
    ax.plot(theta,r,color='r',linewidth=3)
    ax.grid(True)
    
    # 再画一条
    r2 = [5,5,5,5,5]
    r2 = np.empty(5) # 5个空元素
    r2.fill(5) # 元素填充为5
    
    theta2 = [0,np.pi/2,np.pi,np.pi*3/2,0]
    ax.plot(theta2,r2,color='g',lw=3)
    
    plt.show()
    
    # --------------------------------
    # 当然也可以直接采用plt的方法
    # plt.polar()
    

    matplotlib中文显示问题

    #coding:utf-8
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
    plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
    #有中文出现的情况,需要u'内容'
    

    练习项目一:函数积分图

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.patches import Polygon
    
    x = np.linspace(0,10)
    y = -(x-2)*(x-8)+40
    
    fig = plt.figure()
    
    ax = fig.add_subplot(111)
    
    # matplotlib提供长参数的简写,linewidth简写为lw,同理linestyle=ls
    ax.plot(x,y,'r-',lw=2)
    
    # 设置两个积分起止点
    a,b = 2,9
    
    # 调整坐标轴
    ax.set_xticks([a,b])              # 设置点,找到点
    ax.set_xticklabels(['$a$','$b$'])     # 设置tick的标签
    ax.set_yticks([])
    
    # 将右边和上边的框去掉
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.set_xlim(xmin=1)
    #ax.xaxis.set_ticks_position('bottom')
    
    
    # 画坐标轴的显示--这里不太理想,这种方式,可能存在改进
    fig.text(0.9,0.05,'x')
    fig.text(0.1,0.9,'y')
    
    # 画积分区域,patches,多边形polygon,需要一个二维的数组(x,y)序列作为它的边界
    ix = np.linspace(a,b)
    iy = -(ix-2)*(ix-8)+40
    # 这里构造数组的方法用到了zip函数和list函数
    verts = [(a, 0)] + list(zip(ix, iy)) + [(b, 0)]
    # 构建Polygon类型的patches对象,颜色设置利用[0,1]内的数字表示灰度
    poly = Polygon(verts,facecolor='0.9',edgecolor='0.5')
    
    # 画patch
    ax.add_patch(poly)
    
    # 画公式
    str = r'$\int_a^b(-(x-2)(x+8)+40)dx$'
    sx = (a+b)/2
    sy = 35
    # 对齐方式可用 ha简写代替 horizontalalignment
    ax.text(sx,sy,str,fontsize=10,ha='center')
    
    plt.show()
    

    练习项目二:散点图和直方图的联合

    import matplotlib.pyplot as plt
    import numpy as np
    
    # 使用其他的画图样式
    plt.style.use('ggplot')
    
    # 画图数据(正相关的x和y)
    x = np.random.randn(200)
    y = x + np.random.randn(200)*0.8
    
    # 定义一些距离:margin_border,width,height,margin_gap
    # 分别表示, 图边距,散点图宽(正方形),直方图高,散点图和直方图间距
    margin_border,width,height,margin_gap=0.1,0.6,0.2,0.02
    
    # 散点图坐标
    s_bottom_x=margin_border
    s_bottom_y=margin_border
    s_height = s_width = width
    
    # 直方图1坐标
    h1_bootom_x = margin_border
    h1_bootom_y = s_bottom_y+width+margin_gap
    h1_height=height
    h1_width = width
    
    # 直方图2坐标
    h2_bottom_x = margin_border+width+margin_gap
    h2_bottom_y = margin_border
    h2_height=width
    h2_width=height
    
    # 生成相应的轴
    rect = [s_bottom_x,s_bottom_y,s_width,s_height]
    ax_scatter = plt.axes(rect)
    
    rect = [h1_bootom_x,h1_bootom_y,h1_width,h1_height]
    ax_h1 = plt.axes(rect)
    
    rect = [h2_bottom_x,h2_bottom_y,h2_width,h2_height]
    ax_h2 = plt.axes(rect)
    
    # 调整坐标轴,删除一些多余的轴刻度
    ax_h1.set_xticks([])
    ax_h2.set_yticks([])
    
    # 画图
    ax_scatter.scatter(x,y,color='r',alpha=0.5)
    
    # 固定直方图的箱体宽度
    bin_width = 0.25
    # 计算箱数
    maxValue = np.max([np.max(np.fabs(x)),np.max(np.fabs(y))])
    nbins = int(maxValue/0.25+1)
    
    # 根据数据范围为散点图设置刻度范围
    ax_scatter_lim = nbins*bin_width
    ax_scatter.set_xlim(-ax_scatter_lim,ax_scatter_lim)
    ax_scatter.set_ylim(-ax_scatter_lim,ax_scatter_lim)
    
    # 画直方图
    ax_h1.hist(x,bins=nbins,color='g',alpha=0.5)
    ax_h1.set_xlim(ax_scatter.get_xlim())
    ax_h1.locator_params('y',nbins=8)
    
    ax_h2.hist(y,bins=nbins,orientation='horizontal',color='b',alpha=0.5)
    ax_h2.set_ylim(ax_scatter.get_ylim())
    ax_h2.locator_params('x',nbins=8)
    
    plt.show()
    

    相关文章

      网友评论

          本文标题:Matplotlib & Numpy

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