You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何消除plotnine中多父类别与子类别分面图的多余行间距?

如何消除plotnine中多父类别与子类别分面图的多余行间距?

你遇到的这个问题其实是plotnine里facet_wrap的一个小局限——它默认所有分面面板的尺寸都是统一的,哪怕不同父类对应的子类别数量差异很大,也没法自动让面板高度跟着子类别数量调整,所以才会出现多余的空白区域。

要实现面板高度随子类别数量自适应的效果,我们可以换个思路:手动拆分数据,结合matplotlib的子图功能,给每个父类别创建对应高度的子图,再逐个绘制内容。下面是完整的实现方案:

步骤1:准备数据(和你原数据一致)

import pandas as pd

new_data = {
    'date': pd.date_range('2022-01-01', periods=11, freq="ME"),
    'parent_category': ['Electronics', 'Electronics', 'Fashion', 'Fashion', 'Home Goods', 'Electronics', 'Fashion','Electronics','Electronics','Electronics','Electronics'],
    'child_category': ['Smartphones', 'Laptops', 'Shirts', 'Pants', 'Kitchenware','Laptops', 'Shirts', 'Smartphones','PS4','Oven','Vaccum cleaner']
}
new_data = pd.DataFrame(new_data)

步骤2:实现自适应高度的分面图

我们先统计每个父类的子类别数量,以此为依据设置子图的高度比例,再循环绘制每个父类的内容:

import matplotlib.pyplot as plt
from plotnine import *

# 1. 统计每个父类的唯一子类别数量,用于设置子图高度比例
parent_groups = new_data.groupby('parent_category')
parent_names = list(parent_groups.groups.keys())
# 计算每个父类对应的子类别数量
child_counts = [len(group['child_category'].unique()) for _, group in parent_groups]
# 用子类别数量作为子图高度的比例(可以根据需求调整,比如乘以系数让整体高度更合适)
height_ratios = child_counts

# 2. 创建matplotlib子图,指定高度比例
fig, axes = plt.subplots(
    nrows=len(parent_names), 
    ncols=1, 
    figsize=(8, 6), 
    gridspec_kw={'height_ratios': height_ratios}
)
# 调整子图之间的垂直间距
fig.subplots_adjust(hspace=0.6)

# 3. 循环绘制每个父类的内容到对应子图
for ax, parent_name in zip(axes, parent_names):
    # 筛选当前父类别的数据
    subset = new_data[new_data['parent_category'] == parent_name]
    
    # 创建plotnine绘图对象,指定绘制到当前matplotlib轴
    plot = (
        ggplot(subset, aes(x="date", y="child_category", group="child_category")) +
        geom_line(size=1, color="pink") +
        geom_point(size=3, color="grey") +
        theme_538() +
        theme(
            axis_text_x=element_text(angle=45, hjust=1),
            panel_grid_major=element_blank(),
            axis_title_y=element_blank(),  # 隐藏y轴标题,避免重复
            figure_size=None  # 禁用plotnine的自动尺寸设置,用matplotlib的配置
        )
    )
    
    # 将plotnine图形绘制到指定轴
    plot.draw(ax=ax)
    
    # 设置子图标题为父类别名称
    ax.set_title(parent_name, fontweight='bold')
    
    # 优化x轴显示:除了最后一个子图,隐藏x轴标签,避免重复
    if parent_name != parent_names[-1]:
        ax.set_xlabel('')

# 调整整体布局,避免元素重叠
plt.tight_layout()
plt.show()

代码关键点说明

  1. 高度比例计算:我们用每个父类的子类别数量作为子图高度的比例,这样子类越多的父类,对应的子图高度就越高,从根源上消除空白区域。
  2. matplotlib子图控制:通过gridspec_kw={'height_ratios': height_ratios}指定子图的高度比例,这是实现自适应高度的核心。
  3. plotnine与matplotlib结合:用plot.draw(ax=ax)将plotnine的图形绑定到matplotlib的指定轴上,既保留了plotnine的语法便利性,又能利用matplotlib的精细布局控制。

这样实现的图,每个父类的面板高度会完全匹配自身的子类别数量,不会再有多余的空白行啦。

备注:内容来源于stack exchange,提问作者ViSa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 15:08:08