patchworklib
Patchworklib是一个通用的matplotlib相关绘图组合器(包括简单的matplotlib绘图、Seaborn绘图(轴级和图形级)以及plotnine绘图)。这个库的灵感来自ggplot2的patchwork。因此,与原始的patchwork一样,用户可以仅使用"/"和"|"运算符轻松对齐matplotlib绘图。虽然matplotlib正式提供了一个不错的子图组合器"subplot_mosaic",但我认为patchworklib的方式更直观、更灵活。
此外,许多基于matplotlib的第三方库,如plotnine和seaborn,提供了使用简单Python代码生成漂亮图表的功能,但这些图表中的许多不能作为matplotlib子图处理。因此,它们的位置必须手动调整。现在,科学家们花费宝贵的时间来排列图表。
Patchworklib为这个问题提供了解决方案。通过使用patchworklib,任何类型的seaborn和plotnine绘图都可以作为matplotlib子图处理。
加入我们的团队:诚聘生物信息学研究员
我们目前正在寻找一位有生物信息学专业知识的熟练研究员加入我们的实验室。 有关更多详情和申请,请访问以下网址。
安装
对于普通用户,我们建议您按以下方式安装官方发布版:
pip install patchworklib
如果您想使用开发版本,可以使用以下单个命令安装:
pip install git+https://github.com/ponnhide/patchworklib.git
新闻
2023年10月23日:版本0.6.3发布。
- 现在支持Seaborn v0.13.0。
- 我已确认patchworklib仍适用于plotnine v0.12.3。
2023年5月16日:版本0.6.1发布。
- 我无法完全支持plotnine版本0.12.1(它可以工作,但patchworklib的排列结果不如预期)。也许,我将来不会支持plotnine。
- Bricks对象获得了新方法
align_xlabels
和align_ylabels
,这有助于用户对齐给定Brick对象的x/y标签。 - 在stack函数中添加了新参数
equal_spacing
。如果此值为True
,轴边界框应以相等的间距放置。否则,根据x/y刻度标签和x/y标签的文本值,它们可能并不总是等距排列。 - 关闭并可能解决了问题"当子图轴对齐时对齐Bricks的标签。 #40"
- 关闭并可能解决了问题"不适用于Plotnine Seaborn主题。 #37"
- 关闭并可能解决了问题"在plotnine中无法设置标题位置。 #36"
更新日志
2022年12月8日:版本0.5.0发布。
- 添加了新的运算符"+"和"-"。
- 现在支持plotnine > v0.10.x。
- 现在patchworklib可以处理由面向对象的seaborn接口生成的图表。
- 在此存储库中添加了patchworklib提供的每个函数和类的描述。如果您想详细了解如何使用patchworklib,请参阅API.md。
- 更新了patchworklib-examples
2022年8月15日:版本0.4.7发布。
- 修复了一些错误。
- 添加了inset函数。请参见以下示例。
- 在
hstack
和vstack
函数中添加了keep_aspect
参数。 - 示例代码已移至patchworklib-examples
创建嵌入元素
import patchworklib as pw
from plotnine import *
from plotnine.data import *
g1 = pw.load_ggplot(ggplot(mtcars) + geom_point(aes("mpg", "disp")),figsize=(4, 2))
g2 = pw.load_ggplot(ggplot(mtcars) + geom_boxplot(aes("gear", "disp", group = "gear")) + theme_classic())
g12 = pw.inset(g1,g2)
g12.savefig()
g12 = pw.inset(g1,g2, loc="lower left", hratio=0.4, wratio=0.2)
g12.savefig("inset_plotnine2.png")
2022年8月9日:版本0.4.6发布。
- 修复了一些错误(请参见问题#18)。
- 提高了绘图速度。
2022年7月20日:版本0.4.5发布。
- 修复了一些错误。
- 修改了与ggplot主题继承相关的函数。如果您使用patchworklib处理plotnine图表,请务必更新。
- 在Bricks对象中指定绘图(Brick对象)时,您现在可以直接指定Brick对象,而不是Brick对象的标签名称。请参见以下示例。
通过在Bricks对象中指定Brick对象来对齐plotnine图表。
import patchworklib as pw
from plotnine import *
from plotnine.data import *
g1 = pw.load_ggplot(ggplot(mpg, aes(x='cty', color='drv', fill='drv')) +
geom_density(aes(y=after_stat('count')), alpha=0.1) +
scale_color_discrete(guide=False) +
theme(axis_ticks_major_x=element_blank(),
axis_text_x =element_blank(),
axis_title_x=element_blank(),
axis_text_y =element_text(size=12),
axis_title_y=element_text(size=14),
legend_position="none"),
figsize=(4,1))
g2 = pw.load_ggplot(ggplot(mpg, aes(x='hwy', color='drv', fill='drv')) +
geom_density(aes(y=after_stat('count')), alpha=0.1) +
coord_flip() +
theme(axis_ticks_major_y=element_blank(),
axis_text_y =element_blank(),
axis_title_y=element_blank(),
axis_text_x =element_text(size=12),
axis_title_x=element_text(size=14)
),
figsize=(1,4))
g3 = pw.load_ggplot(ggplot(mpg) +
geom_point(aes(x="cty", y="hwy", color="drv")) +
scale_color_discrete(guide=False) +
theme(axis_text =element_text(size=12),
axis_title=element_text(size=14)
),
figsize=(4,4))
pw.param["margin"] = 0.2
(g1/(g3|g2)[g3]).savefig() #通过在(g3|g2)中指定g3,g1正好定位在g3上。
2022年7月19日:版本0.4.3发布。
- 修复了一些错误。
- 添加了
basefigure
参数。您可以通过patchworklib.basefigure
访问patchworklib的基本图形。 - 现在支持plotnine v0.9.0。可能仍存在一些错误。如果您发现错误,请在问题中告诉我。
2022年4月22日:版本0.4.2发布。
- 修复了一些错误。
2022年4月18日:版本0.4.1发布。
load_seaborngrid
现可接受seaborn.clustermap
图表。详情请参见 Google Colab 上的示例代码。- 修复了一些bug。
2022年3月27日:版本0.4.0发布。
- 为每个方法和类添加了文档字符串。
- 为
patchworklib.Bricks
类添加了几个新方法,用于为Bricks
对象中的Brick
对象设置通用标签、标题、轴线和颜色条。 使用方法请参考文档字符串或 Google Colab 上的示例代码。
2022年2月4日:版本0.3.6发布。
- 修复了与排列多个极坐标图对象相关的一些bug。
2022年2月4日:版本0.3.5发布。
- 修复了
move_legend
中的一些bug。(seaborn网格图的move_legend
功能无法正常工作。) - 提高了
savefig
操作的速度。
2022年1月24日:版本0.3.3发布。
- 修复了一些bug。
2022年1月22日:版本0.3.0发布。
Patchworklib 现在支持排列 matplotlib.projections.polar.PolarAxes 对象的功能。
当您将 matplotlib.projections.polar.PolarAxes 对象加载为 Brick 类对象时,请使用 'cBrick' 而不是 'Brick'。 现在,您可以使用 pycircos 和 patchworklib 排列多个圆形图。请参阅以下示例代码。 https://colab.research.google.com/drive/1tkn7pxRqh9By5rTFqRbVNDVws-o-ySz9?usp=sharing
2022年1月21日:版本0.2.1发布。
- 修复了 'load_seaborngrid' 的一些bug。
2022年1月20日:版本0.2.0发布。
Patchworklib 现在可以排列 Seaborn 网格图。添加了 "stack" 功能。修复了一些bug。
排列 Seaborn 网格图
Patchworklib 支持排列基于 axisgrid(FacetGrid、PairGrid 和 JointGrid)生成的多个 Seaborn 图表。 让我们看看以下示例。
import os
import seaborn as sns
import patchworklib as pw
from functools import reduce
pw.overwrite_axisgrid() #使用 pw.load_seagorngrid 时,应执行 'overwrite_axisgrid'。
df = sns.load_dataset("penguins")
g1 = sns.pairplot(df, hue="species")
g1 = pw.load_seaborngrid(g1)
g1.move_legend("upper left", bbox_to_anchor=(0.08,1.01))
planets = sns.load_dataset("planets")
cmap = sns.cubehelix_palette(rot=-.2, as_cmap=True)
g2 = sns.relplot(
data=planets,
x="distance", y="orbital_period",
hue="year", size="mass",
palette=cmap, sizes=(10, 200),
)
g2.set(xscale="log", yscale="log")
g2.ax.xaxis.grid(True, "minor", linewidth=.25)
g2.ax.yaxis.grid(True, "minor", linewidth=.25)
g2.despine(left=True, bottom=True)
g2 = pw.load_seaborngrid(g2)
penguins = sns.load_dataset("penguins")
g3 = sns.jointplot(
data=penguins,
x="bill_length_mm", y="bill_depth_mm", hue="species",
kind="kde",
)
g3 = pw.load_seaborngrid(g3, labels=["joint","marg_x","marg_y"])
((g2/g3["marg_x"])|g1).savefig()
此外,一些示例代码可在 Google Colaboratory 上执行。
"stack" 功能
我实现了 stack
功能。此功能允许用户沿指定方向排列多个(两个以上)Brick 或 Bricks 对象,如下所示。
import patchworklib as pw
ax_list = []
for i in range(10):
ax_list.append(pw.Brick(figsize=(2,2), label="ax{}".format(i)))
stacked_axes = pw.stack(ax_list, operator="|", margin=0.2)
stacked_axes.savefig()
2022年1月14日:版本0.1.0发布。
- Patchworklib 现可通过 pip 安装。
2022年1月13日:实现了 "spacer" 类,并为 Bricks 类添加了 "case" 参数。
在图表周围添加空白空间
#准备图表数据
import numpy as np
import matplotlib as mpl
import patchworklib as pw
data1 = 20 * np.random.rand(100,100) - 10
data2 = 20 * np.random.rand(100,100) - 10
cmap = mpl.cm.Reds
norm = mpl.colors.Normalize(vmin=-10, vmax=10)
ax1 = pw.Brick("axx", figsize=(3,3))
ax2 = pw.Brick("axy", figsize=(3,3))
ax1.imshow(data1, interpolation='nearest', cmap=cmap, aspect="auto")
ax2.imshow(data2, interpolation='nearest', cmap=cmap, aspect="auto")
不使用 spacer
ax_cb = pw.Brick("ax_cb", figsize=(0.1,3))
cb = mpl.colorbar.ColorbarBase(ax_cb, cmap=cmap, norm=norm)
ax12 = ax1|ax2
heatmap2 = ax12 | ax_cb
heatmap2.savefig()
使用 spacer
ax_cb2 = pw.Brick("ax_cb2", figsize=(0.1,1.5))
cb2 = mpl.colorbar.ColorbarBase(ax_cb2, cmap=cmap, norm=norm)
heatmap2 = ax12 | (pw.spacer(ax_cb2,0.5)/ax_cb2/pw.spacer(ax_cb2,0.5))
heatmap2.savefig()
多个图表的总标题
有时,只需为多个图表设置通用标签和标题。
通过指定 Bricks 类对象的 case
参数,可以处理多个图表的通用 matplotlib 艺术家对象。
ax12.case.set_title("多个图表的总标题", pad=10)
heatmap2 = ax12|(pw.spacer(ax_cb,0.5)/ax_cb/pw.spacer(ax_cb,0.5))
heatmap2.savefig("")
01072022: Patchworklib 已更新,以支持排列多个由 plotnine 生成的图表。
import patchworklib as pw
from plotnine import *
from plotnine.data import *
g1 = pw.load_ggplot(ggplot(mtcars) + geom_point(aes("mpg", "disp")) + theme(figure_size=(2, 3)))
g2 = pw.load_ggplot(ggplot(mtcars) + geom_boxplot(aes("gear", "disp", group = "gear")) + theme(figure_size=(2, 3)))
g12 = g1 | g2
g12.savefig()
g3 = pw.load_ggplot(ggplot(mpg, aes(x='displ', y='hwy')) + geom_point() + geom_smooth(span=.3) + theme(figure_size=(2, 3)))
g4 = pw.load_ggplot(ggplot(mtcars) + geom_bar(aes("carb")) + theme(figure_size=(7, 2)))
g1234 = (g1|g2|g3)/g4
g1234.savefig()
使用方法
如果您想详细了解如何使用 patchworklib,请参阅 API.md。
使用 patchworklib
,您可以仅使用 |
和 /
运算符快速自由地排列 matplotlib 图表,如下所示。
import patchworklib as pw
import seaborn as sns
fmri = sns.load_dataset("fmri")
ax1 = pw.Brick(figsize=(3,2))
sns.lineplot(x="timepoint", y="signal", hue="region", style="event", data=fmri, ax=ax1)
ax1.legend(bbox_to_anchor=(1.05, 1.0), loc='upper left')
ax1.set_title("ax1")
titanic = sns.load_dataset("titanic")
ax2 = pw.Brick(figsize=(1,2))
sns.barplot(x="sex", y="survived", hue="class", data=titanic, ax=ax2)
ax2.move_legend(new_loc='upper left', bbox_to_anchor=(1.05, 1.0))
ax2.set_title("ax2")
ax12 = ax1|ax2
ax12.savefig("ax12.png")
所有示例代码的 Jupyter Notebook 文件都可以在 patchworklib-examples 中找到,并且可以在 Google Colaboratory 中执行。
- 教程:patchworklib 的基本示例代码
- plotnine 的子图:使用 patchworklib 排列 plotnine 图表
- seaborngrid 的子图:使用 patchworklib 排列图级别的 seaborn 图表
- 放置超级元素:为一组多个子图放置超级标签和脊线。
另外,请参阅 https://python.plainenglish.io/a-subplot-manager-for-intuitive-layout-in-matplotlib-bd037fe967f4
图库
多个轴级 seaborn 图表的排列
多个 Plotnine 图表的排列
多个图级 seaborn 图表的排列
入门
示例代码
教程 ~组合多个 seaborn 图表~ 以下教程代码可在 tutorial1 中执行
1. 导入 patchworklib 库
import patchworklib as pw
fmri = sns.load_dataset("fmri")
ax1 = pw.Brick("ax1", figsize=(4,2))
sns.lineplot(x="timepoint", y="signal", hue="region", style="event", data=fmri, ax=ax1)
ax1.move_legend(new_loc='upper right')
ax1.set_title("ax1")
2. 创建示例图表
使用 seaborn 模块创建一些示例图表。patchworklib 模块提供的 Brick 类是 matplotlib.axes.Axes
的子类。因此,Brick 类对象可以传递给具有 ax
参数的 seaborn 绘图函数。
在创建 Brick 类对象时,应指定 label
值,并且它在 Python 脚本中生成的 Brick 类对象中应是唯一的(如果未指定 label 值,则会自动给出唯一的标签名称。可以使用 get_label()
方法确认该值)。还可以指定 figsize
参数。但是,该值并不是很重要,因为在排列图表时,Brick 类对象的图形大小可以自动调整。savefig(
filename=str
)
方法返回 matplotlib.figure.Figure
类对象。如果给定 filename
,则可以将图形对象输出到文件。
import seaborn as sns
#示例图表 1(参考:https://seaborn.pydata.org/examples/errorband_lineplots.html)
fmri = sns.load_dataset("fmri")
ax1 = pw.Brick("ax1", figsize=(4,2))
sns.lineplot(x="timepoint", y="signal", hue="region", style="event", data=fmri, ax=ax1)
ax1.move_legend(new_loc='upper right')
ax1.set_title("ax1")
ax1.savefig()
Brick 类提供了 movelegend(
loc=str, bbox_to_anchor=(float,float)
)
方法。使用此方法,可以快速修改图例位置。
#示例图表 2(参考:https://seaborn.pydata.org/tutorial/categorical.html)
titanic = sns.load_dataset("titanic")
ax2 = pw.Brick("ax2", figsize=(1,2))
sns.barplot(x="sex", y="survived", hue="class", data=titanic, ax=ax2)
ax2.move_legend(new_loc='upper left', bbox_to_anchor=(1.05, 1.0)) #Brick 类的原始方法
ax2.set_title("ax2")
ax2.savefig()
#示例图3(参考:https://seaborn.pydata.org/examples/histogram_stacked.html)
diamonds = sns.load_dataset("diamonds")
ax3 = pw.Brick("ax3", (5,2))
sns.histplot(diamonds, x="price", hue="cut", multiple="stack",
palette="light:m_r", edgecolor=".3", linewidth=.5, log_scale=True,
ax = ax3)
ax3.set_title("ax3")
ax3.savefig()
#示例图4(参考:https://seaborn.pydata.org/examples/grouped_violinplots.html)
tips = sns.load_dataset("tips")
ax4 = pw.Brick("ax4", (6,2))
sns.violinplot(data=tips, x="day", y="total_bill", hue="smoker",
split=True, inner="quart", linewidth=1,
palette={"Yes": "b", "No": ".85"},
ax=ax4)
ax4.set_title("ax4")
ax4.savefig("../img/ax4.png")
#示例图5(参考:https://seaborn.pydata.org/examples/wide_data_lineplot.html)
rs = np.random.RandomState(365)
values = rs.randn(365, 4).cumsum(axis=0)
dates = pd.date_range("1 1 2016", periods=365, freq="D")
data = pd.DataFrame(values, dates, columns=["A", "B", "C", "D"])
data = data.rolling(7).mean()
ax5 = pw.Brick("ax5", (5,2))
sns.lineplot(data=data, palette="tab10", linewidth=2.5, ax=ax5)
ax5.set_xlabel("date")
ax5.set_ylabel("value")
ax5.set_title("ax5")
ax5.savefig()
3. 排列和堆叠图表
patchworklib模块提供了两个操作符"|
"和"/
",可以通过简单的操作为多个图表设计整洁的布局。"|
"操作符将图表并排放置,而"/
"操作符将它们堆叠。
#水平排列"ax1"、"ax2"和"ax4"
ax124 = ax1|ax2|ax4
ax124.savefig("../img/ax124.png")
由多个Brick对象(Bricks类对象)排列生成的对象也可以与其他Brick对象进行排列和堆叠。此外,还可以通过嵌套操作创建更复杂的布局。
ax12435 = ax124/(ax3|ax5)
ax12435.savefig("../img/ax12435.png")
你可以通过重新排列它们来快速测试另一种布局。
ax35214 = (ax3/(ax2|ax1))|(ax5/ax4)
ax35214.savefig()
如果你想调整对象之间的边距,请更改.param["margin"]
的值。
pw.param["margin"]=0.2 #默认值为0.5
ax35214 = (ax3/(ax2|ax1))|(ax5/ax4)
ax35214.savefig("../img/ax35214_v1.1.png")
此外,每个图表的宽高比可以自由修改。
pw.param["margin"]=0.5
ax1.change_aspectratio((4,2))
ax3.change_aspectratio((4,1))
ax4.change_aspectratio((5,2))
ax35214_v2 = (ax3/(ax2|ax1))|(ax5/ax4)
ax35214_v2.savefig()
4. 使用标签索引打包图表(高级方法)
通过在Bricks对象中用标签名称指定Brick对象,你可以调整要打包的另一个Brick对象的位置。
ax321 = ax3/(ax2|ax1)
ax321.savefig("../img/ax321.png")
ax3214 = ax321["ax1"]|ax4
ax3214.savefig("../img/ax3214.png")
ax35214_v3 = ax3214["ax3"]|ax5
ax35214_v3.savefig("../img/ax35214_v3.png")
上述打包过程允许对象的坐标轴精确对齐。实际上,在"ax35214"和"ax35214_v2"中,ax3和ax5的底部坐标轴线并不完全对齐,而在"ax35214_v3"中,它们的底部坐标轴线完全对齐。但请注意,这种使用标签索引的打包方法会改变要打包的Brick对象的宽高比,以使其坐标轴线与其他对象对齐。