python绘图专题(matplotlib,Pandas DataFrame)

Matplotlib绘图

user guide: https://matplotlib.org/users/index.html
官方教程:https://www.matplotlib.org.cn/tutorials/
其它教程:https://www.runoob.com/w3cnote/matplotlib-tutorial.html

Matplotlib参数工作逻辑:

figure是放置图表的容器,axes是坐标系,默认情况下,一张纸(figure)被 1个图表(axes)占满
matplotlib里有三个概念:轴-axis,刻度-tick,标签-label,通常我们的操作都是基于axes,因为我们在操作整个图表

图表主要元素的函数说明

函数 核心参数 功能
figure() figsize:图表尺寸,dpi:分辨率 设置图像的大小和分辨率
title() str:图表名称,fontdict:文本格式/字体大小/类型 设置标题
xlabel(),ylabel() xlabel:X轴名,ylabel:Y轴名 设置X/Y轴的标题
axis(),xlim(),ylim() xmin,xmax或ymin,ymax 设置X/Y轴的范围
xticks(),yticks() ticks:刻度数值,labels:刻度名称,fontdict 设置X/Y轴的刻度
grid() b:有无网格,which:主次网格,axis:X/Y轴网格线,color,linestyle,linewidth,alpha:透明度 设置X/Y轴的主要和次要网格线
legend() loc:位置,edgecolor,facecolor,fontsize 控制图例显示

常见图表类型

ID 图表类型 函数 核心参数
1 折线图 plot()
2 散点图/汽泡图 scatter()
3 柱形图/堆积柱形图 bar()
4 条形图/规程条形图 barh
5 面积图 fill_between
6 堆积面积图/量化波形图 stackplot
7 饼图 pie()
8 误差棒 errorbar
9 统计直方图 hist()
10 箱形图 boxplot()
11 垂直X轴直线/垂直Y轴直线 axhline(),axvline()
12 垂直X轴矩形/垂直Y轴矩形 axhspan(),axvspan()
13 指定位置文本 text()
14 指定数据点标注 annotate()

plt.setp(对象)查看对象可设置的属性 --一个好用的入门方法

plt.setp本身也是一种快速批量修改属性的方法,可以查看axes的众多属性

plt.setp(axes)

plt.setp(axes)
  adjustable: {'box', 'datalim'}
  agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
  alpha: float or None
  anchor: 2-tuple of floats or {'C', 'SW', 'S', 'SE', ...}
  animated: bool
  aspect: {'auto'} or num
  autoscale_on: bool
  autoscalex_on: bool
  autoscaley_on: bool
  axes_locator: Callable[[Axes, Renderer], Bbox]
  axisbelow: bool or 'line'
  box_aspect: None, or a number
  clip_box: `.Bbox`
  clip_on: bool
  clip_path: Patch or (Path, Transform) or None
  contains: unknown
  facecolor or fc: color
  figure: `.Figure`
  frame_on: bool
  gid: str
  in_layout: bool
  label: object
  navigate: bool
  navigate_mode: unknown
  path_effects: `.AbstractPathEffect`
  picker: None or bool or callable
  position: [left, bottom, width, height] or `~matplotlib.transforms.Bbox`
  prop_cycle: unknown
  rasterization_zorder: float or None
  rasterized: bool or None
  sketch_params: (scale: float, length: float, randomness: float)
  snap: bool or None
  subplotspec: unknown
  title: str
  transform: `.Transform`
  url: str
  visible: bool
  xbound: unknown
  xlabel: str
  xlim: (bottom: float, top: float)
  xmargin: float greater than -0.5
  xscale: {"linear", "log", "symlog", "logit", ...}
  xticklabels: unknown
  xticks: unknown
  ybound: unknown
  ylabel: str
  ylim: (bottom: float, top: float)
  ymargin: float greater than -0.5
  yscale: {"linear", "log", "symlog", "logit", ...}
  yticklabels: unknown
  yticks: unknown
  zorder: float

以上属性,获取的方式是:axes.get_xticklabels(),即使用“前缀+下划线+属性名”来调用。
也可以再查看它的子属性,如plt.setp(axes.get_xticklabels())或plt.setp(axes.get_xticklabels()[0]),但是不是每个子属性都可以用plt.setp()查看下去的。

再比如:

plt.setp(fig)

plt.setp(fig)
  agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
  alpha: float or None
  animated: bool
  canvas: FigureCanvas
  clip_box: `.Bbox`
  clip_on: bool
  clip_path: Patch or (Path, Transform) or None
  constrained_layout: bool or dict or None
  constrained_layout_pads: unknown
  contains: unknown
  dpi: float
  edgecolor: color
  facecolor: color
  figheight: float
  figure: `.Figure`
  fig float
  frameon: bool
  gid: str
  in_layout: bool
  label: object
  path_effects: `.AbstractPathEffect`
  picker: None or bool or callable
  rasterized: bool or None
  size_inches: (float, float) or float
  sketch_params: (scale: float, length: float, randomness: float)
  snap: bool or None
  tight_layout: bool or dict with keys "pad", "w_pad", "h_pad", "rect" or None
  transform: `.Transform`
  url: str
  visible: bool
  zorder: float

以上的这些属性,我们会在后面用到。
面向对象设计,意味着图表上能看到的对象都有一个对象代表它,matplotlib的灵活在于对细节的控制。

查看自定义对象的属性(非常重要!)

通过查看自定义对象的属性, 可以方便修改,举个简单的例子:

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

df = pd.DataFrame({'year':[1565,1570,1575,1580,1585],'wheat':[41,45,42,49,41.5],'wages':[5,5.05,5.08,5.12,5.15]})
df.year = df.year.astype(str)

fig,axes = plt.subplots()
fig.set_figwidth(20)
fig.set_figheight(10)
bar = axes.bar(df.year,df.wheat)

这里定义了 bar, 它是一个 <BarContainer object of 5 artists>
为了修改它, 我们可以用plt.setp(bar)来查看它的属性。

plt.setp(bar)
  agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
  alpha: float or None
  animated: bool
  antialiased or aa: unknown
  bounds: (left, bottom, width, height)
  capstyle: {'butt', 'round', 'projecting'}
  clip_box: `.Bbox`
  clip_on: bool
  clip_path: Patch or (Path, Transform) or None
  color: color
  contains: unknown
  edgecolor or ec: color or None or 'auto'
  facecolor or fc: color or None
  figure: `.Figure`
  fill: bool
  gid: str
  hatch: {'/', '\', '|', '-', '+', 'x', 'o', 'O', '.', '*'}
  height: unknown
  in_layout: bool
  joinstyle: {'miter', 'round', 'bevel'}
  label: object
  linestyle or ls: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
  linewidth or lw: float or None
  path_effects: `.AbstractPathEffect`
  picker: None or bool or callable
  rasterized: bool or None
  sketch_params: (scale: float, length: float, randomness: float)
  snap: bool or None
  transform: `.Transform`
  url: str
  visible: bool
   unknown
  x: unknown
  xy: (float, float)
  y: unknown
  zorder: float

知道了它的属性,我们就能方便的对它进行操作。具体内容见“设置颜色”一节。

设置画布的大小

第一种方法:直接在subplots里用figsize=(x,y)指定:
fig,axes = plt.subplots(figsize=(20,10))
第二种方法:用plt.setp方式找到属性 figwidth, figheight

fig.set_figwidth(20)
fig.set_figheight(10)

以上两种方法等效。

设置颜色

接查看自定义对象的属性(非常重要!)的例子:

min_bar = df.wheat.idxmin()     #idxmin()是对一列求最小,返回其索引值 ,而非数据本身
max_bar = df.wheat.idxmax()

bar[min_bar].set_color('orange')
bar[max_bar].set_color('red')

设置图表标题和水平线

axes.set(title = 'wheat each year', xlabel = 'year',ylabel='wheat')
axes.axhline(df.wheat.mean(),c='red',ls='--')

设置图表字体大小

plt.rcParams.update({'axes.titlesize':45,'axes.labelsize':25})
plt.rcParams.update({'font.size':20})

绘图实例

1.折线图 plot()详解

绘制plot图-- 极简起步 plt.plot(x,y)

import numpy as np 
from matplotlib import pyplot as plt 
 
x = np.arange(1,11) 
y =  2  * x +  5 
plt.title("Matplotlib demo") 
plt.xlabel("x axis caption") 
plt.ylabel("y axis caption") 
plt.plot(x,y) 
plt.show()

绘制plot --讲解设定

import numpy as np 
from matplotlib import pyplot as plt 

# 创建一个 8 * 6 点(point)的图,并设置分辨率为 80
fig = plt.figure(figsize=(10,5),dpi=80) 
# 创建一个新的 1 * 1 的子图,接下来的图样绘制在其中的第 1 块(也是唯一的一块)
plt.subplot(1,1,1)

X = np.linspace(-np.pi, np.pi, 256,endpoint=True)
C,S = np.cos(X), np.sin(X)

# 绘制余弦曲线,使用蓝色的、连续的、宽度为 1 (像素)的线条
plt.plot(X, C, color="blue", linewidth=1.0, linestyle="-")
# 绘制正弦曲线,使用绿色的、连续的、宽度为 1 (像素)的线条
plt.plot(X, S, color="green", linewidth=1.0, linestyle="-")

# 设置横轴的上下限
plt.xlim(-4.0,4.0)
# 设置横轴记号
plt.xticks(np.linspace(-4,4,9,endpoint=True))
# 设置纵轴的上下限
plt.ylim(-1.0,1.0)
# 设置纵轴记号
plt.yticks(np.linspace(-1,1,5,endpoint=True))

# 以分辨率 72 来保存图片
# savefig("exercice_2.png",dpi=72)
# 在屏幕上显示
plt.show()

绘制plot --进阶: 设定线型/颜色/粗细/标签

import numpy as np 
from matplotlib import pyplot as plt 

fig = plt.figure(figsize=(10,5))
data = np.linspace(0,10,100)      
#在指定的间隔范围内返回均匀间隔的数字。在[start, stop]范围内计算,返回num个(默认为50)均匀间隔的样本。
#参考:https://blog.csdn.net/benben_dog/article/details/85446452

plt.plot(data, np.sin(data), c='r',ls='--',lw=4,label="label name")
plt.xlabel('I am X Axis')
plt.ylabel('I am Y Axis')
plt.title("data desc")
plt.legend()
plt.show()

绘制plot -- 另一个角度出发,设置风格并保存

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

# Data for plotting
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)

fig, ax = plt.subplots()
ax.plot(t, s)

ax.set(xlabel='time (s)', ylabel='voltage (mV)',
       title='About as simple as it gets, folks')
ax.grid()

fig.savefig("test.png")
plt.show()

绘制plot --双曲线图 plt.plot(x,y)

import numpy as np 
from matplotlib import pyplot as plt 

fig = plt.figure(figsize=(10,5))
data = np.linspace(0,10,100)
plt.plot(data, np.sin(data), 'r-o', label="test legend A")
plt.plot(data, np.cos(data), 'g--', label="test legend B")

# 两个线也可以这样写: plt.plot(x_line1, y_line2, 'r', x_line2, y_line2, 'b')
# 尝试取消下面注释运行(这种方式, 貌似图例不方便分开配置)
# plt.plot(data, np.sin(data), 'r-o', data, np.cos(data), 'g--', label="A")

plt.xlabel('I am X Axis')
plt.ylabel('I am Y Axis')
plt.title("data desc")
plt.legend()
plt.show()

绘制多个plot --双图 plt.plot(x,y)

import numpy as np 
from matplotlib import pyplot as plt 
x1 = np.linspace(0.0, 5.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
x2 = np.linspace(0.0, 2.0)
y2 = np.cos(2 * np.pi * x2)

plt.subplot(2, 1, 1)
plt.plot(x1, y1, 'o-')
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')

plt.subplot(2, 1, 2)
plt.plot(x2, y2, '.-')
plt.xlabel('time (s)')
plt.ylabel('Undamped')

plt.show()

绘制多个plot --双图(for循环写)

import numpy as np
import matplotlib.pyplot as plt
 
plt.figure(1) # 创建图表1
plt.figure(2) # 创建图表2
ax1 = plt.subplot(211) # 在图表2中创建子图1
ax2 = plt.subplot(212) # 在图表2中创建子图2
 
x = np.linspace(0, 3, 100)
for i in range(5):
    plt.figure(1)  # 选择图表1
    plt.plot(x, np.exp(i*x/3))
    plt.sca(ax1)   # 选择图表2的子图1
    plt.plot(x, np.sin(i*x))
    plt.sca(ax2)  # 选择图表2的子图2
    plt.plot(x, np.cos(i*x))
 
plt.show()

2 散点图/汽泡图 scatter()

绘制scatter(x,y)入门

import numpy as np 
from matplotlib import pyplot as plt 
x = np.linspace(0.05,10,1000)
y = np.random.rand(1000)
plt.scatter(x,y,label='scatter figure')
plt.legend()
plt.show()

Matplotlib图表的导出

plt.savefig()函数可以将Matplotlib图表导出不同的格式,包括pdf,png,jpg,svg等,注意:plt和word共同支持的格式有:jpg,jpeg,png,svg,tif,tiff
其中,只有svg矢量图保存到word后不会模糊,其它格式的文件保存后模糊都十分严重。
例:导出到pdf的代码如下:

plt.savefig('filename.pdf',format='pdf')
plt.show()  # plt.savefig()必须 在plt.show()之前调用

如果要保持图片的清晰度,可以使用:

plt.savefig('test.png',dpi=600)
plt.show()

Matplotlib中文支持问题

Matplotlib 默认情况不支持中文,我们可以使用以下简单的方法来解决。
1.从本机COPY一个字体到py文件的目录中
并且在python语句中加入下一句:

zhfont1 = matplotlib.font_manager.FontProperties(fname="Deng.ttf")  #这里引用的是'等线'中文字体

然后就可以在title或lable中引用了。效果如下:

import numpy as np 
from matplotlib import pyplot as plt 
import matplotlib

# fname 为你指定的字体库路径
zhfont1 = matplotlib.font_manager.FontProperties(fname="Deng.ttf") 
 
x = np.arange(1,11) 
y =  2  * x +  5 
plt.title("菜鸟教程 - 测试", fontproperties=zhfont1) 
 
# fontproperties 设置中文显示,fontsize 设置字体大小
plt.xlabel("x 轴", fontproperties=zhfont1)
plt.ylabel("y 轴", fontproperties=zhfont1)
plt.plot(x,y) 
plt.show()

如果不知道把字体文件放在哪里,可以运行下一句命令,直接打开当前py文件所在的目录

import os
working_path = os.getcwd()
os.system("explorer.exe %s" % working_path)    #打开py文件所在的目录

2.不更新任何字体,直接使用命令:

import numpy as np 
from matplotlib import pyplot as plt 
import matplotlib as mpl

mpl.rcParams['font.sans-serif'] = ['KaiTi']
mpl.rcParams['font.serif'] = ['KaiTi']
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题,或者转换负号为字符串
 
x = np.arange(1,11) 
y =  2  * x +  5 
plt.title("菜鸟教程 - 测试") 
 
plt.xlabel("x 轴")
plt.ylabel("y 轴")
plt.plot(x,y) 
plt.show()

其中,第三句mpl.rcParams['axes.unicode_minus'] = False是用来排除 ‘RuntimeWarning: Glyph 8722 missing from current font.’错误提示的
上面那三句写成这样也是可以的:

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

3.使用网上的思源黑体,思源黑体是 Adobe 与 Google 推出的一款开源字体。
官网:https://source.typekit.com/source-han-serif/cn/
GitHub 地址:https://github.com/adobe-fonts/source-han-sans/tree/release/OTF/SimplifiedChinese
打开链接后,在里面选一个就好了:
你也可以在网盘下载: https://pan.baidu.com/s/14cRhgYvvYotVIFkRVd71fQ 提取码: e15r。
可以下载个 OTF 字体,比如 SourceHanSansSC-Bold.otf,将该文件文件放在当前执行的代码文件中

Pandas DataFrame绘图

对于普通的二维表,如果df只有2列,可以用下面的命令直接画折线图:

df.plot()

参考网站

matplotlib中文网
https://www.matplotlib.org.cn/

《Python数据可视化之matplotlib实践》 作者:刘大成 中国工信出版社

原文地址:https://www.cnblogs.com/treasury-manager/p/14246955.html