Python中的分类气泡图
Posted
技术标签:
【中文标题】Python中的分类气泡图【英文标题】:Categorical bubble plot in Python 【发布时间】:2021-05-23 11:07:46 【问题描述】:我有一个包含很多分类变量和二进制目标变量的数据集。 Python 或其他基于开源 GUI 的软件中提供了哪些软件包,我可以在其中散点图 X 和 Y 轴上的两个分类变量并将目标变量用作色调?
我查看了 Seaborn 的 catplot,但为此,一个轴必须是数字的,而另一个轴必须是分类的。所以它不适用于这种情况。
例如,您可以使用以下内容:
import seaborn as sns
data = sns.load_dataset('titanic')
这是我想要的剧情功能
X 轴 - 'embark_town' Y 轴 - '类' 色调 - '活着'
【问题讨论】:
你可以用 pyplot 来做。提供数据样本和预期输出。 pakpe - 我已将数据添加到帖子中。请回复。 @Mr. T - Seaborn 很漂亮,但非 Seaborn 也可以。 Alive 具有值“是”和“否”。我在脑海中将 X 和 Y 变量的频率显示为是和否的气泡。不确定这在任何 python 包中是否可行。我尝试在谷歌上搜索,但找不到任何内容。 【参考方案1】:我的观点是,如果您必须大量重新排列 seaborn 图,您也可以使用 matplotlib 从头开始创建此图。这使我们有机会采用不同的方法来显示此分类与分类图:
import matplotlib.pyplot as plt
from matplotlib.markers import MarkerStyle
import numpy as np
#dataframe and categories
import seaborn as sns
df = sns.load_dataset('titanic')
X = "embark_town"
Y = "class"
H = "alive"
bin_dic = 0: "yes", 1: "no"
#counting the X-Y-H category entries
plt_df = df.groupby([X, Y, H]).size().to_frame(name="vals").reset_index()
#figure preparation with grid and scaling
fig, ax = plt.subplots(figsize=(9, 6))
ax.set_ylim(plt_df[Y].unique().size-0.5, -0.5)
ax.set_xlim(-0.5, plt_df[X].unique().size+1.0)
ax.grid(ls="--")
#upscale factor for scatter marker size
scale=10000/plt_df.vals.max()
#left marker for category 0
ax.scatter(plt_df[plt_df[H]==bin_dic[0]][X],
plt_df[plt_df[H]==bin_dic[0]][Y],
s=plt_df[plt_df[H]==bin_dic[0]].vals*scale,
c=[(0, 0, 1, 0.5)], edgecolor="black", marker=MarkerStyle("o", fillstyle="left"),
label=bin_dic[0])
#right marker for category 1
ax.scatter(plt_df[plt_df[H]==bin_dic[1]][X],
plt_df[plt_df[H]==bin_dic[1]][Y],
s=plt_df[plt_df[H]==bin_dic[1]].vals*scale,
c=[(1, 0, 0, 0.5)], edgecolor="black", marker=MarkerStyle("o", fillstyle="right"),
label=bin_dic[1])
#legend entries for the two categories
l = ax.legend(title="Survived the catastrophe", ncol=2, framealpha=0, loc="upper right", columnspacing=0.1,labelspacing=1.5)
l.legendHandles[0]._sizes = l.legendHandles[1]._sizes = [800]
#legend entries representing sizes
bubbles_n=5
bubbles_min = 50*(1+plt_df.vals.min()//50)
bubbles_step = 10*((plt_df.vals.max()-bubbles_min)//(10*(bubbles_n-1)))
bubbles_x = plt_df[X].unique().size+0.5
for i, bubbles_y in enumerate(np.linspace(0.5, plt_df[Y].unique().size-1, bubbles_n)):
#plot each legend bubble to indicate different marker sizes
ax.scatter(bubbles_x,
bubbles_y,
s=(bubbles_min + i*bubbles_step) * scale,
c=[(1, 0, 1, 0.6)], edgecolor="black")
#and label it with a value
ax.annotate(bubbles_min+i*bubbles_step, xy=(bubbles_x, bubbles_y),
ha="center", va="center",
fontsize="large", fontweight="bold", color="white")
plt.show()
【讨论】:
非常感谢!【参考方案2】:Seaborn 像 matplotlib 一样支持分类变量与分类变量的绘图。可以创建允许查看两个类别的半透明标记,尽管如果两者具有相似的大小,这可能难以与一个标记区分开来。基本图相当简单 - 我们使用 groupby 和 size 转换数据框,以计算每个三胞胎出发城镇 - 班级 - 活着类别的条目,然后创建一个以计数值作为标记大小的散点图。但是,图例条目是这里复杂的部分。标记大小在情节中很小或在图例中很大。我试图平衡这一点,但我对结果不满意。这里需要大量的手动调整,所以 seaborn 在这里没有真正的优势。欢迎任何有关如何在 seaborn 中简化此操作的建议。
import seaborn as sns
import matplotlib.pyplot as plt
#dataframe and categories
df = sns.load_dataset('titanic')
X = "embark_town"
Y = "class"
H = "alive"
#counting the X-Y-H category entries
plt_df = df.groupby([X, Y, H]).size().to_frame(name="people").reset_index()
#figure preparation with grid and scaling
fig, ax = plt.subplots(figsize=(6,4))
ax.set_ylim(plt_df[Y].unique().size-0.5, -0.5)
ax.set_xlim(-0.5, plt_df[X].unique().size+1.0)
ax.grid(ls="--")
#the actual scatterplot with markersize representing the counted values
sns.scatterplot(x=X,
y=Y,
size="people",
sizes=(100, 10000),
alpha=0.5,
edgecolor="black",
hue=H,
data=plt_df,
ax=ax)
#creating two legends because the hue markers differ in size from the others
handles, labels = ax.get_legend_handles_labels()
l = ax.legend(handles[:3], labels[:3], title="The poor die first", markerscale=2, loc="upper right")
ax.add_artist(l)
#and seaborn plots the size markers in black, so you would get massive black blobs in the legend
#we change the color and make them transparent
for handle in handles:
handle.set_facecolors((0, 1, 1, 0.5))
ax.legend(handles[4::2], labels[4::2], title="N° of people", loc="lower right", handletextpad=4, labelspacing=3, markerfirst=False)
plt.tight_layout()
plt.show()
样本输出:
【讨论】:
真的,非常感谢。非常感谢。以上是关于Python中的分类气泡图的主要内容,如果未能解决你的问题,请参考以下文章
如何在 python/matplotlib 中制作居中气泡图