做科研的小伙伴可能经常要与画图打交道,好马配好鞍,优秀的结果如果没有恰当的图形来展示,不得不说是一种遗憾。
而一个图好不好看,主要取决于以下几个方法:
matplotlib是python中最常用的绘图第三方库,基本可以实现绝大多数图形的绘制(很优秀),本文将分享一种高效的matplotlib绘图流程,让你轻轻松松五步作图。
import matplotlib.pyplot as plt # 导入matplotlib
# 1.数据准备
x, y = [1, 2], [3, 4]
# 2.建立画板
plt.figure()
# 3.编写绘图逻辑
plt.plot(x, y, 'r-')
# 4.显示图形
plt.show() #
优点:代码量少,能快速作图(草图)
缺点:一图一例, 代码复用率很低
import matplotlib.pyplot as plt # 导入matplotlib
# 1.数据准备
x, y = [1, 2], [3, 4]
# 2.建立画板与画笔
fig, axes = plt.subplots()
# 3.使用画笔绘制关键图形
axes.plot(x,
y,
color=‘r',
linewidth=2,
linestyle='dashed')
# 4.匹配模板
axes.set_xlim([1, 2])
axes.set_ylim([3, 4])
axes.set_xlabel(kwargs.get("xlabel")
axes.set_ylabel(kwargs.get("ylabel")
# 5.图形显示与保存
fig.show()
fig.savefig('test.pdf',dpi=500,bbox_inches='tight')
新的绘图模式,能更好的模拟我们的画图习惯,设想一下,我们平常是怎么画图的呢?
第一步:在脑子里构想好想要画的东西(数据准备)
第二步:准备好画板和画笔(建立画板与画笔)
第三步:用画笔在画板上画出主体部分,并给它上色什么的(使用画笔绘制关键图形)
第四步:签上自己的大名,创作日期之类的(匹配模板)
第五步:保存大作,并展示给别人看(图形显示与保存)
伟人曾经说过,python一切皆对象,对象才是python标准的玩法。所以,我们有必要提炼一些对象出来。
Preprocessing类:数据的预处理(准备数据)
Axes类:画笔对象,用来绘制各类图形
Template类:模板对象,给你的大作配上帅气的logo
Postprocessing类:后续处理,如图形的显示与保存
PythonMatplotlib类:控制画图的主逻辑,完成上文提到的5步
对象化之后,由于画笔与模板的分离,我们只需要不断地完善Axes类和Template类(在Axes添加新的图形,在Template中添加新的配置项),就能画出越来越好看地图形。
接下来,我们将利用具体地实例,展示"五步法"绘制简单图形的过程(实例参考自:Matplotlib Python 画图教程 (莫烦Python))
import matplotlib.pyplot as plt
import numpy as np
class Preprocessing:
def import_data(self):
"""
绘制简单曲线
"""
x = np.linspace(-10, 10, 50)
y = 2 * x + 1
return x, y
class Postprocessing:
def fig_show(self):
plt.tight_layout()
self.fig.show()
plt.pause(3)
plt.close()
def fig_save(self, **kwargs):
save_name = kwargs.get("save_name", "untitled")
self.fig.savefig(save_name + '.pdf',
dpi=500,
bbox_inches='tight')
class Template:
def common_template(self, **kwargs):
# 配置坐标轴与原点位置(spines): 是否使用笛卡尔坐标系
if kwargs.get("cartesian"):
# gca = 'get current axis'
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
# ACCEPTS: [ 'top' | 'bottom' | 'both' | 'default' | 'none' ]
ax.spines['bottom'].set_position(('data', 0))
# the 1st is in 'outward' | 'axes' | 'data'
# axes: percentage of y axis
# data: depend on y data
ax.yaxis.set_ticks_position('left')
# ACCEPTS: [ 'left' | 'right' | 'both' | 'default' | 'none' ]
ax.spines['left'].set_position(('data', 0))
# 设置图像有效范围(lim)
self.axes.set_xlim(kwargs.get("xlim"))
self.axes.set_ylim(kwargs.get("ylim"))
if kwargs.get("zlim"):
self.axes.set_zlim(kwargs.get("zlim"))
# 设置坐标轴名称(label)
if kwargs.get("xlabel"):
self.axes.set_xlabel(kwargs.get("xlabel"))
if kwargs.get("ylabel"):
self.axes.set_ylabel(kwargs.get("ylabel"))
# 设置坐标轴刻度(ticks)和标签(tick_labels)
if type(kwargs.get("xticks")) == np.ndarray or kwargs.get(
"xticks") == [] or kwargs.get("xticks"):
self.axes.set_xticks(kwargs.get("xticks"))
if type(kwargs.get("yticks")) == np.ndarray or kwargs.get(
"yticks") == [] or kwargs.get("yticks"):
self.axes.set_yticks(kwargs.get("yticks"))
if kwargs.get("xtick_labels"):
self.axes.set_xticklabels(kwargs.get("xtick_labels"))
if kwargs.get("ytick_labels"):
self.axes.set_yticklabels(kwargs.get("ytick_labels"))
# 设置图例(legend)
if kwargs.get("show_legend"):
plt.legend(loc=kwargs.get("loc"))
elif kwargs.get("legend_labels"):
plt.legend(handles=self.handles[0]
if len(self.handles) == 1 else self.handles,
labels=kwargs.get("legend_labels"),
loc=kwargs.get("loc", "best"))
# 设置标题
if kwargs.get("title"):
self.axes.set_title(kwargs.get("title"),
fontsize=12,
fontname="Times New Roman")
# 对数坐标
if kwargs.get("xlog"):
self.axes.set_xscale('log')
if kwargs.get("ylog"):
self.axes.set_yscale('log')
# # 设置坐标轴刻度的字体
if kwargs.get("tick_font"):
labels = self.axes.get_xticklabels() + self.axes.get_yticklabels()
for label in labels:
label.set_fontname('Times New Roman')
label.set_fontsize(kwargs.get("tick_font"))
label.set_bbox(
dict(facecolor=kwargs.get("facecolor", "white"),
edgecolor=kwargs.get("edgecolor", "none"),
alpha=kwargs.get("alpha", 0.8),
zorder=kwargs.get("zorder", 2)))
# 设置色标(colorbar)
if kwargs.get("colorbar"):
plt.colorbar(shrink=kwargs.get("shrink", .92))
return
class Axes:
def draw_line(self, x, y, **kwargs):
# the "," is very important in here l1, = plt... and l2, = plt... for this step
l, = self.axes.plot(x,
y,
color=kwargs.get('color'),
marker=kwargs.get('marker'),
markersize=kwargs.get('markersize', 4),
markerfacecolor=kwargs.get('markerfacecolor'),
alpha=kwargs.get('alpha', 1),
linewidth=2,
linestyle='dashed')
return l
class PythonMatplotlib(Preprocessing, Postprocessing, Template, Axes):
def __init__(self, **kwargs):
# 数据准备
self.data = self.import_data()
# 建立画板与画笔
self.fig, self.axes = plt.subplots(num=kwargs.get("num"),
figsize=kwargs.get("figsize"))
self.handles = []
# 常用配置
self.ALPHA = [1, 1, 1, 1, 1, 1]
self.COLOR = [plt.get_cmap('tab20c').colors[i] for i in [0, 4, 8, 12, 16, 18]]
self.MARKER = ['^', 'o', 's', '*', '+', 'D']
self.MARKER_COLOR = [plt.get_cmap('tab20c').colors[i] for i in [1, 5, 8, 12, 16, 18]]
def simple_line(self, **kwargs):
# 绘制图形
self.draw_line(*self.data, color='red', linewidth=1.0, linestyle='--')
# 使用模板
self.common_template(xlim=(-1, 2),
ylim=(-2, 3),
xlabel="I am x",
ylabel="I am y",
xticks=np.linspace(-1, 2, 5),
yticks=[-2, -1.8, -1, 1.22, 3],
ytick_labels=[
r'$really\ bad$', r'$bad$', r'$normal$',
r'$good$', r'$really\ good$'
])
# 输出与保存(PDF)
if kwargs.get("fig_show", True):
self.fig_show()
if kwargs.get("save_as_pdf"):
self.fig_save(save_as_pdf=kwargs.get("save_as_pdf"),
save_name=kwargs.get("save_name", "simple_line"))
if __name__ == '__main__':
client = PythonMatplotlib()
client.simple_line(save_as_pdf=True)
五步法绘制简单图形流程:
具体使用过程:
GitHub入口