数据可视化

作者:技能派办公效率v1

使用 matplotlib 和 seaborn 创建出版级质量的分析图表,支持柱状图、折线图、散点图、热力图、直方图、箱线图和 multi-panel 综合分析摘要。当用户需要数据可视化、绘制图表、创建数据报告、展示统计分析结果时触发。触发词:数据可视化、图表、绘图、数据分析图、可视化报告

下载量
288
点赞
72
价格
免费

技能文档

---
name: data-visualization
title: 数据可视化
category: 办公效率
description: 使用 matplotlib 和 seaborn 创建出版级质量的分析图表,支持柱状图、折线图、散点图、热力图、直方图、箱线图和 multi-panel 综合分析摘要。当用户需要数据可视化、绘制图表、创建数据报告、展示统计分析结果时触发。触发词:数据可视化、图表、绘图、数据分析图、可视化报告
---

# 数据可视化技能

使用 matplotlib 和 seaborn 在无头环境中创建出版级质量分析图表,保存为 PNG 文件供查看。

## 适用场景

- 可视化数据分析或机器学习模型结果
- 创建各类图表(柱状图、折线图、散点图、热力图、直方图、箱线图)
- 构建多面板综合分析摘要
- 用户需要可视化输出、图表、图形
- 用图表展示统计发现

## 技能工作流

### 步骤1:初始化绘图环境

必须在导入 pyplot 之前调用 `matplotlib.use('Agg')` 启用无头渲染。

```python
import matplotlib
matplotlib.use('Agg')  # 无头后端——必须在 pyplot 导入之前
import matplotlib.pyplot as plt
import numpy as np

# 出版级质量默认配置
plt.rcParams.update({
    'figure.dpi': 100,
    'savefig.dpi': 300,
    'font.size': 11,
    'axes.labelsize': 12,
    'axes.titlesize': 14,
    'xtick.labelsize': 10,
    'ytick.labelsize': 10,
    'legend.fontsize': 10,
    'figure.constrained_layout.use': True,
})

# 色盲安全调色板 (Okabe-Ito)
COLORS = ['#0173B2', '#DE8F05', '#029E73', '#D55E00', '#CC78BC',
          '#CA9161', '#FBAFE4', '#949494', '#ECE133', '#56B4E9']
```

### 步骤2:保存图表

始终使用以下设置保存图表:

```python
plt.savefig('chart_name.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

- `dpi=300` 确保打印质量
- `bbox_inches='tight'` 去除多余空白
- `facecolor='white'` 确保白色背景
- 保存后始终调用 `plt.close()` 释放内存

### 步骤3:展示图表

保存图表后,使用文件读取工具展示图表,确保用户可以看到可视化结果。

### 步骤4:选择图表类型

根据数据特征选择合适的图表类型,参考下方快速参考。

## 快速参考

### 柱状图(分组统计结果)

```python
# 前置: result = to_pd(df.groupby("category")["value"].mean())
fig, ax = plt.subplots(figsize=(8, 5))

bars = ax.bar(result.index, result.values, color=COLORS[:len(result)],
              edgecolor='black', linewidth=0.8)

for bar in bars:
    height = bar.get_height()
    ax.text(bar.get_x() + bar.get_width()/2., height,
            f'{height:.1f}', ha='center', va='bottom', fontsize=9)

ax.set_ylabel('Mean Value', fontweight='bold')
ax.set_xlabel('Category', fontweight='bold')
ax.set_title('Average Value by Category', fontweight='bold')
ax.grid(axis='y', alpha=0.3, linestyle='--')
ax.set_axisbelow(True)

plt.savefig('bar_chart.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 折线图(趋势变化)

```python
fig, ax = plt.subplots(figsize=(10, 5))

for i, col in enumerate(columns_to_plot):
    ax.plot(df["date"], df[col], label=col, color=COLORS[i], linewidth=2,
            marker='o', markersize=3, markevery=max(1, len(df)//20))

ax.set_ylabel('Values', fontweight='bold')
ax.set_xlabel('Date', fontweight='bold')
ax.set_title('Trends Over Time', fontweight='bold')
ax.legend(frameon=True, shadow=False)
ax.grid(True, alpha=0.3, linestyle='--')
ax.set_axisbelow(True)
plt.xticks(rotation=45, ha='right')

plt.savefig('line_chart.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 散点图——连续着色(相关性分析)

```python
fig, ax = plt.subplots(figsize=(8, 6))

scatter = ax.scatter(df["x"], df["y"], c=df["value"], cmap='viridis',
                     s=40, alpha=0.7, edgecolors='black', linewidth=0.3)
plt.colorbar(scatter, ax=ax, label='Value')

# 可选: 趋势线
z = np.polyfit(df["x"], df["y"], 1)
ax.plot(df["x"].sort_values(), np.poly1d(z)(df["x"].sort_values()),
        "r--", linewidth=2, label=f'y={z[0]:.2f}x+{z[1]:.2f}')

ax.set_xlabel('X', fontweight='bold')
ax.set_ylabel('Y', fontweight='bold')
ax.set_title('Correlation Analysis', fontweight='bold')
ax.legend()
ax.grid(True, alpha=0.3, linestyle='--')

plt.savefig('scatter_correlation.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 散点图——分类着色(聚类展示)

```python
fig, ax = plt.subplots(figsize=(8, 6))

for i, label in enumerate(sorted(df["cluster"].unique())):
    mask = df["cluster"] == label
    ax.scatter(df.loc[mask, "x"], df.loc[mask, "y"],
               c=COLORS[i], label=f'Cluster {label}', s=40, alpha=0.7)

ax.set_xlabel('X', fontweight='bold')
ax.set_ylabel('Y', fontweight='bold')
ax.set_title('Cluster Visualization', fontweight='bold')
ax.legend()
ax.grid(True, alpha=0.3, linestyle='--')

plt.savefig('scatter_clusters.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 热力图(相关矩阵或混淆矩阵)

```python
import seaborn as sns

fig, ax = plt.subplots(figsize=(8, 7))

# corr_matrix = to_pd(df[numeric_cols].corr())
sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='RdBu_r', center=0,
            square=True, linewidths=1, vmin=-1, vmax=1,
            cbar_kws={'label': 'Correlation'}, ax=ax)

ax.set_title('Correlation Matrix', fontweight='bold')

plt.savefig('heatmap.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 直方图 + KDE 密度曲线

```python
fig, ax = plt.subplots(figsize=(8, 5))

ax.hist(df["value"], bins=30, color=COLORS[0], alpha=0.7,
        edgecolor='black', linewidth=0.5, density=True, label='Distribution')

# 添加 KDE 曲线
from scipy.stats import gaussian_kde
kde = gaussian_kde(df["value"].dropna())
x_range = np.linspace(df["value"].min(), df["value"].max(), 200)
ax.plot(x_range, kde(x_range), color=COLORS[1], linewidth=2, label='KDE')

ax.set_xlabel('Value', fontweight='bold')
ax.set_ylabel('Density', fontweight='bold')
ax.set_title('Value Distribution', fontweight='bold')
ax.legend()
ax.grid(axis='y', alpha=0.3, linestyle='--')

plt.savefig('histogram.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 箱线图(分组对比)

```python
fig, ax = plt.subplots(figsize=(8, 5))

groups = [df[df["group"] == g]["value"].values for g in group_names]
bp = ax.boxplot(groups, labels=group_names, patch_artist=True,
                widths=0.6, showmeans=True,
                meanprops=dict(marker='D', markerfacecolor='red', markersize=6))

for i, patch in enumerate(bp['boxes']):
    patch.set_facecolor(COLORS[i % len(COLORS)])
    patch.set_alpha(0.7)

ax.set_ylabel('Value', fontweight='bold')
ax.set_title('Distribution by Group', fontweight='bold')
ax.grid(axis='y', alpha=0.3, linestyle='--')
ax.set_axisbelow(True)

plt.savefig('boxplot.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 多面板综合分析摘要

使用单个图像展示多个图表,是呈现完整分析最有效的方式。

```python
fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 左上: 分布图
axes[0, 0].hist(df["value"], bins=30, color=COLORS[0], alpha=0.7, edgecolor='black', linewidth=0.5)
axes[0, 0].set_title('Value Distribution', fontweight='bold')
axes[0, 0].set_xlabel('Value')
axes[0, 0].grid(axis='y', alpha=0.3, linestyle='--')

# 右上: 散点图
axes[0, 1].scatter(df["x"], df["y"], c=COLORS[0], s=30, alpha=0.5)
axes[0, 1].set_title('X vs Y', fontweight='bold')
axes[0, 1].set_xlabel('X')
axes[0, 1].set_ylabel('Y')
axes[0, 1].grid(True, alpha=0.3, linestyle='--')

# 左下: 柱状图
group_means = df.groupby("category")["value"].mean()
axes[1, 0].bar(group_means.index, group_means.values, color=COLORS[:len(group_means)])
axes[1, 0].set_title('Mean by Category', fontweight='bold')
axes[1, 0].set_xlabel('Category')
axes[1, 0].grid(axis='y', alpha=0.3, linestyle='--')

# 右下: 箱线图
axes[1, 1].boxplot([df[df["category"] == c]["value"].values for c in categories],
                    labels=categories, patch_artist=True)
axes[1, 1].set_title('Distribution by Category', fontweight='bold')
axes[1, 1].grid(axis='y', alpha=0.3, linestyle='--')

fig.suptitle('Analysis Summary', fontsize=16, fontweight='bold')

plt.savefig('analysis_summary.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 特征重要性图(机器学习模型)

```python
fig, ax = plt.subplots(figsize=(8, max(4, len(feature_names) * 0.35)))

# importances = to_pd(model.feature_importances_)
sorted_idx = np.argsort(importances)
ax.barh(np.array(feature_names)[sorted_idx], importances[sorted_idx],
        color=COLORS[0], edgecolor='black', linewidth=0.5)

ax.set_xlabel('Importance', fontweight='bold')
ax.set_title('Feature Importances', fontweight='bold')
ax.grid(axis='x', alpha=0.3, linestyle='--')
ax.set_axisbelow(True)

plt.savefig('feature_importance.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

### 混淆矩阵(分类模型评估)

```python
import seaborn as sns

fig, ax = plt.subplots(figsize=(7, 6))

# cm = confusion_matrix(to_pd(y_test), to_pd(predictions))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', square=True,
            xticklabels=class_names, yticklabels=class_names,
            linewidths=1, cbar_kws={'label': 'Count'}, ax=ax)

ax.set_xlabel('Predicted', fontweight='bold')
ax.set_ylabel('Actual', fontweight='bold')
ax.set_title('Confusion Matrix', fontweight='bold')

plt.savefig('confusion_matrix.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')
plt.close()
```

## 样式规范

- 使用 `COLORS` 色盲安全调色板——不单独依赖颜色区分元素
- 不使用饼图(柱状图总是更清晰)
- 不使用 3D 图表(会扭曲数据感知)
- 网格线设置 `alpha=0.3, linestyle='--'` 并配合 `ax.set_axisbelow(True)`
- 轴标签和标题加粗(`fontweight='bold'`)
- 所有导出使用白色背景
- 每次分析 1-4 张图表;更多内容使用多面板布局

## 输出规范

- 所有图表保存为 PNG 格式
- 保存后打印文件路径以便引用
- 多面板摘要使用 `figsize=(14, 10)` 的 2×2 布局
- 图表标题简洁描述性强
- 轴标签包含单位(如适用)

使用说明

# 数据可视化

使用 matplotlib 和 seaborn 创建出版级质量分析图表,支持柱状图、折线图、散点图、热力图、直方图、箱线图及多面板综合分析。

## 使用

在对话中直接描述可视化需求即可:

```
帮我画一张用户年龄分布的直方图
```

```
用散点图展示 x 和 y 的相关性,并按类别着色
```

```
生成一个 2×2 多面板分析摘要,包含分布、散点、柱状和箱线图
```

## 支持的图表类型

- 柱状图、折线图、散点图(连续/分类着色)
- 热力图、直方图 + KDE 密度曲线
- 箱线图、多面板综合分析
- 特征重要性图、混淆矩阵

## 工作原理

基于 matplotlib 无头渲染后端,图表保存为 300dpi 高清 PNG。使用色盲安全调色板(Okabe-Ito),所有图表自动应用出版级样式配置。

如何安装此技能?

访问技能市场,点击「安装」按钮,按提示将技能包放入 AI 编程助手的 skills 目录即可。

浏览技能市场

支持平台:Qoder · QoderWork · Claude · Codex 等 AI 编程助手