---
name: opensensenova/category-statistics
source: https://app.decimal.ai/s/opensensenova-category-statistics@1/SKILL.md
source_sha256: 1e3d53719bb8
---

## Skill Steps

Step1 提取目标类别数据，清洗无效标签，并统计各类别数量与占比。
```python
import pandas as pd

def calculate_distribution(data, target_col='类别'):
    # 检查目标列是否存在
    if target_col not in data.columns:
        raise ValueError(f'未找到指定的类别字段: {target_col}')
    
    # 提取数据，清洗无效标签（如'--'、'代码'等占位符）
    category_data = data[target_col].dropna().replace(['--', '代码'], pd.NA).dropna()
    
    # 统计各类别数量并计算占比
    counts = category_data.value_counts()
    proportions = (counts / counts.sum()) * 100
    
    # 实用技巧：生成包含总计行的统计表
    # summary = counts.copy()
    # summary.loc['总计'] = counts.sum()
    
    return counts, proportions
```

Step2 生成基础可视化（双轴图：柱状图+占比曲线），并保存为高分辨率图片。
```python
import matplotlib.pyplot as plt

def generate_and_save_basic_chart(counts, proportions, title='各类别数量分布', output_path='category_distribution.png'):
    # 设置中文字体避免乱码
    plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Zen Hei', 'Noto Sans CJK JP', 'DejaVu Sans']
    plt.rcParams['axes.unicode_minus'] = False
    
    fig, ax1 = plt.subplots(figsize=(10, 6))
    
    # 绘制柱状图
    bars = ax1.bar(counts.index, counts.values, color='skyblue', edgecolor='black')
    for bar in bars:
        height = bar.get_height()
        ax1.text(bar.get_x() + bar.get_width()/2., height + 0.05, f'{height}', ha='center', va='bottom', fontsize=10)
    
    ax1.set_ylabel('数量', fontsize=12)
    ax1.set_title(title, fontsize=16, fontweight='bold', pad=20)
    
    # 创建第二个y轴显示占比曲线
    ax2 = ax1.twinx()
    ax2.plot(counts.index, proportions.values, color='red', marker='o', linestyle='-', linewidth=2)
    ax2.set_ylabel('占比 (%)', color='red', fontsize=12)
    ax2.tick_params(axis='y', labelcolor='red')
    
    plt.xticks(rotation=45)
    plt.tight_layout()
    
    # 保存高分辨率图表并使用 plt.close() 防止内存泄漏
    fig.savefig(output_path, dpi=300, bbox_inches='tight')
    plt.close(fig)
    
    return output_path
```

Step3 生成多图组合报告（饼图+柱状图，以及带分类映射的水平柱状图），用于多维度展示。
```python
import matplotlib.pyplot as plt
from matplotlib.patches import Patch

def generate_comprehensive_report(counts, proportions, output_dir='./'):
    plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Zen Hei', 'Noto Sans CJK JP', 'DejaVu Sans']
    plt.rcParams['axes.unicode_minus'] = False
    
    # --- 1. 饼图与柱状图组合 ---
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
    
    # 饼图
    colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
    explode = [0.05] * len(counts) if len(counts) > 0 else None
    wedges, texts, autotexts = ax1.pie(counts.values, labels=counts.index, autopct='%1.1f%%',
                                       colors=colors[:len(counts)], explode=explode, shadow=True, startangle=90)
    ax1.set_title('各类别比例分布', fontsize=14, fontweight='bold')
    for autotext in autotexts:
        autotext.set_color('white')
        autotext.set_fontweight('bold')
    
    # 柱状图
    bars = ax2.bar(range(len(counts)), counts.values, color=colors[:len(counts)], alpha=0.8, edgecolor='black')
    ax2.set_title('各类别数量', fontsize=14, fontweight='bold')
    ax2.set_xticks(range(len(counts)))
    ax2.set_xticklabels(counts.index, rotation=45, ha='right')
    
    for i, bar in enumerate(bars):
        height = bar.get_height()
        ax2.text(bar.get_x() + bar.get_width()/2., height + 0.5, f'{int(height)}\n({proportions.iloc[i]:.1f}%)',
                 ha='center', va='bottom', fontweight='bold')
    
    plt.tight_layout()
    pie_bar_path = f'{output_dir}category_pie_bar.png'
    plt.savefig(pie_bar_path, dpi=300, bbox_inches='tight')
    plt.close(fig)
    
    # --- 2. 水平柱状图 (带分类映射函数骨架与颜色区分) ---
    fig_h, ax_h = plt.subplots(figsize=(12, 8))
    positions = [f'类别{i+1}' for i in range(len(counts))]
    
    # 分类映射示例：根据类别名称包含的关键字动态分配颜色
    bar_colors = ['#66b3ff' if '关键字A' in str(p) else '#ff9999' for p in counts.index]
    bars_h = ax_h.barh(positions, counts.values, color=bar_colors, alpha=0.8, edgecolor='black')
    
    ax_h.set_title('各类别分布详情', fontsize=16, fontweight='bold', pad=20)
    
    for i, (bar, label) in enumerate(zip(bars_h, counts.index)):
        width = bar.get_width()
        # 动态标签示例：提取特定属性
        tag = '类型A' if '关键字A' in str(label) else '其他'
        ax_h.text(width + 0.3, bar.get_y() + bar.get_height()/2, f'{int(width)} ({tag})',
                  ha='left', va='center', fontsize=10)
    
    # 自定义图例
    legend_elements = [Patch(facecolor='#66b3ff', label='类型A组'), Patch(facecolor='#ff9999', label='其他组')]
    ax_h.legend(handles=legend_elements, loc='lower right')
    ax_h.grid(axis='x', alpha=0.3)
    
    plt.tight_layout()
    hbar_path = f'{output_dir}category_hbar.png'
    plt.savefig(hbar_path, dpi=300, bbox_inches='tight')
    plt.close(fig_h)
    
    return [pie_bar_path, hbar_path]
```