個人開発している円形データプロットのためのPython製OSSライブラリ「pyCirclize」に積み上げ棒グラフのプロット機能を最近追加してみた。この記事では、新しく追加した円形の積み上げ棒プロット機能の使い方について簡単に紹介します。
pyCirclizeのインストール
pip
または conda
コマンドでインストール可能
PyPIからインストール
pip install pycirclize
conda-forgeからインストール
conda install -c conda-forge pycirclize
積み上げ棒グラフのプロット
pyCirclizeでは行名・列名付きの表データ
から円形の積み上げ棒グラフを垂直・水平方向にそれぞれプロットする機能を実装してます。
垂直方向プロット例①
from pycirclize import Circos
import pandas as pd
import numpy as np
np.random.seed(0)
# Generate matrix data for stacked bar plot
row_num, col_num = 12, 6
matrix = np.random.randint(5, 20, (row_num, col_num))
row_names = [f"R{i}" for i in range(row_num)]
col_names = [f"group{i}" for i in range(col_num)]
table_df = pd.DataFrame(matrix, index=row_names, columns=col_names)
table_df.to_csv("stacked_bar_table.tsv", sep="\t")
# Initialize Circos sector & track
circos = Circos(sectors=dict(bar=len(table_df.index)))
sector = circos.sectors[0]
track = sector.add_track((50, 100))
track.grid()
# Plot stacked bar
colormap = "Set3"
sb_table = track.stacked_bar(
table_df,
width=0.6,
cmap=colormap,
bar_kws=dict(ec="black", lw=0.2),
label_pos="bottom",
label_kws=dict(size=10, orientation="horizontal"),
)
circos.savefig("stacked_bar01.png")
入力
行名・列名付き表データ(TSV形式)
group0 group1 group2 group3 group4 group5
R0 17 10 5 8 16 8
R1 12 14 8 10 7 9
R2 12 11 13 13 17 15
R3 6 11 12 12 19 13
R4 6 10 14 18 13 14
R5 9 8 5 8 10 19
R6 5 7 8 13 6 8
R7 18 8 8 19 12 5
R8 6 14 14 5 15 9
R9 12 8 19 16 7 12
R10 17 7 5 5 9 10
R11 10 11 13 9 6 9
出力図
垂直方向プロット例②
最小限のプロットのみだった垂直方向プロット例①
から凡例や最小・最大値ラベルを追加した例
from pycirclize import Circos
from matplotlib.patches import Patch
import pandas as pd
import numpy as np
np.random.seed(0)
# Generate matrix data for stacked bar plot
row_num, col_num = 12, 6
matrix = np.random.randint(5, 20, (row_num, col_num))
row_names = [f"R{i}" for i in range(row_num)]
col_names = [f"group{i}" for i in range(col_num)]
table_df = pd.DataFrame(matrix, index=row_names, columns=col_names)
# Initialize Circos sector & track (5 <= range <= 355)
circos = Circos(sectors=dict(bar=len(table_df.index)), start=5, end=355)
sector = circos.sectors[0]
track = sector.add_track((50, 100))
track.grid(x_grid_interval=track.size)
# Plot stacked bar & label
colormap = "tab10"
sb_table = track.stacked_bar(
table_df,
width=0.6,
cmap=colormap,
bar_kws=dict(ec="black", lw=0.2),
label_pos="top",
label_kws=dict(size=10, orientation="vertical"),
)
vmin, vmax = 0, sb_table.row_sum_vmax
circos.text(str(vmin), r=min(track.r_lim), color="grey")
circos.text(str(vmax), r=max(track.r_lim), color="grey")
fig = circos.plotfig()
# Plot legends
col_name2color = sb_table.get_col_name2color(colormap)
_ = circos.ax.legend(
handles=[Patch(label=n, fc=c, ec="black", lw=0.5) for n, c in col_name2color.items()],
bbox_to_anchor=(0.5, 0.5),
loc="center",
ncols=2,
)
fig.savefig("stacked_bar02.png")
出力図
水平方向プロット例
from pycirclize import Circos
from pycirclize.parser import StackedBarTable
from matplotlib.patches import Patch
import pandas as pd
import numpy as np
np.random.seed(0)
# Generate & load matrix data for horizontal stacked bar plot
row_names = list("ABCDEF")
col_names = ["group1", "group2", "group3", "group4", "group5", "group6"]
matrix = np.random.randint(5, 20, (len(row_names), len(col_names)))
table_df = pd.DataFrame(matrix, index=row_names, columns=col_names)
table_df.to_csv("stacked_barh_table.tsv", sep="\t")
sb_table = StackedBarTable(table_df)
# Initialize Circos sector & track (0 <= range <= 270)
circos = Circos(sectors=dict(bar=sb_table.row_sum_vmax), start=0, end=270)
sector = circos.sectors[0]
track = sector.add_track((30, 100))
track.axis(fc="lightgrey", ec="black", alpha=0.5)
# Plot horizontal stacked bar & label & xticks
colormap = "tab10"
track.stacked_barh(sb_table.dataframe, cmap=colormap, width=0.6)
label_r_list = sb_table.calc_barh_label_r_list(track.r_plot_lim)
for label_r, row_name in zip(label_r_list, sb_table.row_names):
track.text(f"{row_name} ", x=0, r=label_r, ha="right")
track.xticks_by_interval(interval=5)
track.xticks_by_interval(interval=1, tick_length=1, show_label=False)
fig = circos.plotfig()
# Plot legends
col_name2color = sb_table.get_col_name2color(colormap)
_ = circos.ax.legend(
handles=[Patch(label=n, fc=c, ec="black", lw=0.5) for n, c in col_name2color.items()],
bbox_to_anchor=(0.2, 0.8),
fontsize=12,
loc="center",
ncols=2,
)
fig.savefig("stacked_barh.png")
入力
行名・列名付き表データ(TSV形式)
group1 group2 group3 group4 group5 group6
A 17 10 5 8 16 8
B 12 14 8 10 7 9
C 12 11 13 13 17 15
D 6 11 12 12 19 13
E 6 10 14 18 13 14
F 9 8 5 8 10 19
出力図
おわりに
matplotlibで円形の積み上げ棒グラフをプロットするコードを一から実装しようとすると、そこそこ手間がかかります。pyCirclizeを利用することで、比較的簡単に積み上げ棒グラフを作成できるようになると思います。円形の積み上げ棒グラフを使うことはあまりないと思いますが、興味を持った人がいれば使ってみてください。