Skip to content

Pandas 数据可视化

数据可视化是数据分析的重要组成部分,它能够帮助我们直观地理解数据的分布、趋势和模式。Pandas 提供了强大的可视化功能,可以与 matplotlib 和 seaborn 无缝集成,让我们能够快速创建各种类型的图表。

1. 可视化基础设置

1.1 环境配置

python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体和负号显示
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

# 设置图表样式
plt.style.use('seaborn-v0_8')
sns.set_palette("husl")

# 设置图表大小
plt.rcParams['figure.figsize'] = (12, 8)
plt.rcParams['font.size'] = 10

print("可视化环境配置完成")

1.2 创建示例数据集

python
# 设置随机种子
np.random.seed(42)

# 创建综合数据集
n_samples = 1000

# 销售数据
sales_data = {
    'date': pd.date_range('2022-01-01', periods=365, freq='D'),
    'product': np.random.choice(['产品A', '产品B', '产品C', '产品D', '产品E'], 365),
    'region': np.random.choice(['北区', '南区', '东区', '西区'], 365),
    'sales_amount': np.random.normal(1000, 300, 365),
    'quantity': np.random.randint(10, 100, 365),
    'customer_satisfaction': np.random.uniform(3.0, 5.0, 365)
}

# 确保销售额为正数
sales_data['sales_amount'] = np.maximum(sales_data['sales_amount'], 100)

sales_df = pd.DataFrame(sales_data)
sales_df['month'] = sales_df['date'].dt.month
sales_df['quarter'] = sales_df['date'].dt.quarter
sales_df['weekday'] = sales_df['date'].dt.day_name()

# 员工数据
employee_data = {
    'employee_id': range(1, n_samples + 1),
    'department': np.random.choice(['IT', 'HR', 'Finance', 'Marketing', 'Operations'], n_samples),
    'position': np.random.choice(['初级', '中级', '高级', '专家', '经理'], n_samples),
    'salary': np.random.normal(8000, 2000, n_samples),
    'age': np.random.randint(22, 60, n_samples),
    'experience_years': np.random.randint(0, 20, n_samples),
    'performance_score': np.random.uniform(60, 100, n_samples)
}

employee_data['salary'] = np.maximum(employee_data['salary'], 3000)
employee_df = pd.DataFrame(employee_data)

print("示例数据集创建完成")
print(f"销售数据: {sales_df.shape}")
print(f"员工数据: {employee_df.shape}")

2. 基础图表类型

2.1 线图 (Line Plot)

python
print("\n=== 线图示例 ===")

# 时间序列线图
fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# 1. 基本时间序列线图
daily_sales = sales_df.groupby('date')['sales_amount'].sum()
daily_sales.plot(ax=axes[0,0], color='blue', linewidth=2)
axes[0,0].set_title('每日销售额趋势')
axes[0,0].set_ylabel('销售额')
axes[0,0].grid(True, alpha=0.3)

# 2. 多条线图
product_daily_sales = sales_df.groupby(['date', 'product'])['sales_amount'].sum().unstack()
product_daily_sales.plot(ax=axes[0,1], marker='o', markersize=3)
axes[0,1].set_title('各产品每日销售额')
axes[0,1].set_ylabel('销售额')
axes[0,1].legend(title='产品', bbox_to_anchor=(1.05, 1), loc='upper left')
axes[0,1].grid(True, alpha=0.3)

# 3. 滚动平均线图
daily_sales_ma = daily_sales.rolling(window=7).mean()
axes[1,0].plot(daily_sales.index, daily_sales.values, alpha=0.3, label='原始数据')
axes[1,0].plot(daily_sales_ma.index, daily_sales_ma.values, color='red', linewidth=2, label='7日移动平均')
axes[1,0].set_title('销售额与移动平均')
axes[1,0].set_ylabel('销售额')
axes[1,0].legend()
axes[1,0].grid(True, alpha=0.3)

# 4. 面积图
region_daily_sales = sales_df.groupby(['date', 'region'])['sales_amount'].sum().unstack()
region_daily_sales.plot.area(ax=axes[1,1], alpha=0.7)
axes[1,1].set_title('各区域销售额堆叠面积图')
axes[1,1].set_ylabel('销售额')
axes[1,1].legend(title='区域', bbox_to_anchor=(1.05, 1), loc='upper left')

plt.tight_layout()
plt.show()

# 使用 Pandas 内置绘图方法
print("\n使用 Pandas 内置方法绘制线图:")
# 月度销售趋势
monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
monthly_sales.plot(kind='line', marker='o', title='月度销售额趋势', figsize=(10, 6))
plt.ylabel('销售额')
plt.xlabel('月份')
plt.grid(True, alpha=0.3)
plt.show()

2.2 柱状图 (Bar Plot)

python
print("\n=== 柱状图示例 ===")

fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# 1. 基本柱状图
product_sales = sales_df.groupby('product')['sales_amount'].sum().sort_values(ascending=False)
product_sales.plot(kind='bar', ax=axes[0,0], color='skyblue')
axes[0,0].set_title('各产品总销售额')
axes[0,0].set_ylabel('销售额')
axes[0,0].tick_params(axis='x', rotation=45)

# 2. 水平柱状图
region_sales = sales_df.groupby('region')['sales_amount'].sum().sort_values()
region_sales.plot(kind='barh', ax=axes[0,1], color='lightcoral')
axes[0,1].set_title('各区域总销售额')
axes[0,1].set_xlabel('销售额')

# 3. 分组柱状图
product_region_sales = sales_df.groupby(['product', 'region'])['sales_amount'].sum().unstack()
product_region_sales.plot(kind='bar', ax=axes[1,0])
axes[1,0].set_title('产品-区域销售额分组柱状图')
axes[1,0].set_ylabel('销售额')
axes[1,0].tick_params(axis='x', rotation=45)
axes[1,0].legend(title='区域', bbox_to_anchor=(1.05, 1), loc='upper left')

# 4. 堆叠柱状图
product_region_sales.plot(kind='bar', stacked=True, ax=axes[1,1])
axes[1,1].set_title('产品-区域销售额堆叠柱状图')
axes[1,1].set_ylabel('销售额')
axes[1,1].tick_params(axis='x', rotation=45)
axes[1,1].legend(title='区域', bbox_to_anchor=(1.05, 1), loc='upper left')

plt.tight_layout()
plt.show()

# 员工数据柱状图
print("\n员工数据柱状图:")
fig, axes = plt.subplots(1, 2, figsize=(15, 6))

# 部门人数分布
dept_count = employee_df['department'].value_counts()
dept_count.plot(kind='bar', ax=axes[0], color='lightgreen')
axes[0].set_title('各部门人数分布')
axes[0].set_ylabel('人数')
axes[0].tick_params(axis='x', rotation=45)

# 职位分布
position_count = employee_df['position'].value_counts()
position_count.plot(kind='pie', ax=axes[1], autopct='%1.1f%%')
axes[1].set_title('职位分布饼图')
axes[1].set_ylabel('')

plt.tight_layout()
plt.show()

2.3 散点图 (Scatter Plot)

python
print("\n=== 散点图示例 ===")

fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# 1. 基本散点图
employee_df.plot.scatter(x='age', y='salary', ax=axes[0,0], alpha=0.6)
axes[0,0].set_title('年龄与薪资关系')
axes[0,0].set_xlabel('年龄')
axes[0,0].set_ylabel('薪资')

# 2. 带颜色分组的散点图
for dept in employee_df['department'].unique():
    dept_data = employee_df[employee_df['department'] == dept]
    axes[0,1].scatter(dept_data['experience_years'], dept_data['salary'], 
                     label=dept, alpha=0.6)
axes[0,1].set_title('工作经验与薪资关系(按部门分组)')
axes[0,1].set_xlabel('工作经验(年)')
axes[0,1].set_ylabel('薪资')
axes[0,1].legend()

# 3. 气泡图(散点大小表示第三个变量)
scatter = axes[1,0].scatter(employee_df['age'], employee_df['salary'], 
                           s=employee_df['performance_score']*2, 
                           c=employee_df['experience_years'], 
                           alpha=0.6, cmap='viridis')
axes[1,0].set_title('年龄-薪资-绩效-经验综合散点图')
axes[1,0].set_xlabel('年龄')
axes[1,0].set_ylabel('薪资')
colorbar = plt.colorbar(scatter, ax=axes[1,0])
colorbar.set_label('工作经验(年)')

# 4. 销售数据散点图
sales_df.plot.scatter(x='quantity', y='sales_amount', 
                     c='customer_satisfaction', 
                     colormap='RdYlBu', ax=axes[1,1], alpha=0.6)
axes[1,1].set_title('销量与销售额关系(颜色表示客户满意度)')
axes[1,1].set_xlabel('销量')
axes[1,1].set_ylabel('销售额')

plt.tight_layout()
plt.show()

# 相关性矩阵散点图
print("\n相关性分析散点图:")
numeric_cols = ['age', 'salary', 'experience_years', 'performance_score']
fig, ax = plt.subplots(figsize=(10, 8))
pd.plotting.scatter_matrix(employee_df[numeric_cols], ax=ax, alpha=0.6, diagonal='hist')
plt.suptitle('员工数据相关性矩阵散点图')
plt.tight_layout()
plt.show()

2.4 直方图和密度图

python
print("\n=== 直方图和密度图示例 ===")

fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# 1. 基本直方图
employee_df['salary'].plot.hist(bins=30, ax=axes[0,0], alpha=0.7, color='skyblue')
axes[0,0].set_title('薪资分布直方图')
axes[0,0].set_xlabel('薪资')
axes[0,0].set_ylabel('频数')

# 2. 密度图
employee_df['salary'].plot.density(ax=axes[0,1], color='red', linewidth=2)
axes[0,1].set_title('薪资分布密度图')
axes[0,1].set_xlabel('薪资')
axes[0,1].set_ylabel('密度')

# 3. 分组直方图
for dept in employee_df['department'].unique():
    dept_salary = employee_df[employee_df['department'] == dept]['salary']
    axes[1,0].hist(dept_salary, alpha=0.5, label=dept, bins=20)
axes[1,0].set_title('各部门薪资分布对比')
axes[1,0].set_xlabel('薪资')
axes[1,0].set_ylabel('频数')
axes[1,0].legend()

# 4. 多变量密度图
for dept in employee_df['department'].unique():
    dept_salary = employee_df[employee_df['department'] == dept]['salary']
    dept_salary.plot.density(ax=axes[1,1], alpha=0.7, label=dept)
axes[1,1].set_title('各部门薪资密度分布对比')
axes[1,1].set_xlabel('薪资')
axes[1,1].set_ylabel('密度')
axes[1,1].legend()

plt.tight_layout()
plt.show()

# 使用 seaborn 绘制更美观的分布图
print("\n使用 Seaborn 绘制分布图:")
fig, axes = plt.subplots(1, 2, figsize=(15, 6))

# 直方图 + 密度图
sns.histplot(data=employee_df, x='salary', hue='department', 
            kde=True, ax=axes[0], alpha=0.6)
axes[0].set_title('各部门薪资分布(直方图+密度图)')

# 小提琴图
sns.violinplot(data=employee_df, x='department', y='salary', ax=axes[1])
axes[1].set_title('各部门薪资分布(小提琴图)')
axes[1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

3. 高级图表类型

3.1 箱线图 (Box Plot)

python
print("\n=== 箱线图示例 ===")

fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# 1. 基本箱线图
employee_df.boxplot(column='salary', ax=axes[0,0])
axes[0,0].set_title('薪资分布箱线图')
axes[0,0].set_ylabel('薪资')

# 2. 分组箱线图
employee_df.boxplot(column='salary', by='department', ax=axes[0,1])
axes[0,1].set_title('各部门薪资分布箱线图')
axes[0,1].set_xlabel('部门')
axes[0,1].set_ylabel('薪资')

# 3. 多变量箱线图
employee_df[['salary', 'age', 'performance_score']].boxplot(ax=axes[1,0])
axes[1,0].set_title('多变量箱线图')
axes[1,0].tick_params(axis='x', rotation=45)

# 4. 使用 seaborn 绘制更美观的箱线图
sns.boxplot(data=employee_df, x='position', y='salary', ax=axes[1,1])
axes[1,1].set_title('各职位薪资分布箱线图')
axes[1,1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

# 销售数据箱线图
print("\n销售数据箱线图:")
fig, axes = plt.subplots(1, 2, figsize=(15, 6))

# 各产品销售额箱线图
sns.boxplot(data=sales_df, x='product', y='sales_amount', ax=axes[0])
axes[0].set_title('各产品销售额分布')
axes[0].tick_params(axis='x', rotation=45)

# 各区域销售额箱线图
sns.boxplot(data=sales_df, x='region', y='sales_amount', ax=axes[1])
axes[1].set_title('各区域销售额分布')

plt.tight_layout()
plt.show()

3.2 热力图 (Heatmap)

python
print("\n=== 热力图示例 ===")

fig, axes = plt.subplots(2, 2, figsize=(15, 12))

# 1. 相关性热力图
corr_matrix = employee_df[['age', 'salary', 'experience_years', 'performance_score']].corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0, ax=axes[0,0])
axes[0,0].set_title('员工数据相关性热力图')

# 2. 透视表热力图
product_region_pivot = sales_df.pivot_table(
    values='sales_amount', 
    index='product', 
    columns='region', 
    aggfunc='mean'
)
sns.heatmap(product_region_pivot, annot=True, fmt='.0f', cmap='YlOrRd', ax=axes[0,1])
axes[0,1].set_title('产品-区域平均销售额热力图')

# 3. 时间序列热力图
sales_df['day'] = sales_df['date'].dt.day
month_day_sales = sales_df.pivot_table(
    values='sales_amount',
    index='month',
    columns='day',
    aggfunc='mean'
)
sns.heatmap(month_day_sales, cmap='viridis', ax=axes[1,0], cbar_kws={'label': '平均销售额'})
axes[1,0].set_title('月份-日期销售额热力图')
axes[1,0].set_xlabel('日期')
axes[1,0].set_ylabel('月份')

# 4. 部门-职位薪资热力图
dept_position_salary = employee_df.pivot_table(
    values='salary',
    index='department',
    columns='position',
    aggfunc='mean'
)
sns.heatmap(dept_position_salary, annot=True, fmt='.0f', cmap='plasma', ax=axes[1,1])
axes[1,1].set_title('部门-职位平均薪资热力图')

plt.tight_layout()
plt.show()

# 缺失值热力图
print("\n缺失值分析热力图:")
# 创建带缺失值的数据
df_with_missing = employee_df.copy()
np.random.seed(42)
for col in ['salary', 'age', 'performance_score']:
    missing_idx = np.random.choice(df_with_missing.index, size=50, replace=False)
    df_with_missing.loc[missing_idx, col] = np.nan

# 绘制缺失值热力图
plt.figure(figsize=(10, 6))
sns.heatmap(df_with_missing.isnull(), cbar=True, yticklabels=False, cmap='viridis')
plt.title('数据缺失值分布热力图')
plt.show()

3.3 多子图布局

python
print("\n=== 多子图布局示例 ===")

# 创建复杂的多子图布局
fig = plt.figure(figsize=(20, 15))

# 使用 GridSpec 创建自定义布局
from matplotlib.gridspec import GridSpec
gs = GridSpec(3, 4, figure=fig, hspace=0.3, wspace=0.3)

# 第一行:时间序列分析
ax1 = fig.add_subplot(gs[0, :2])
daily_sales = sales_df.groupby('date')['sales_amount'].sum()
daily_sales.plot(ax=ax1, color='blue', linewidth=2)
ax1.set_title('每日销售额趋势', fontsize=14)
ax1.grid(True, alpha=0.3)

ax2 = fig.add_subplot(gs[0, 2:])
monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
monthly_sales.plot(kind='bar', ax=ax2, color='orange')
ax2.set_title('月度销售额分布', fontsize=14)
ax2.tick_params(axis='x', rotation=0)

# 第二行:产品和区域分析
ax3 = fig.add_subplot(gs[1, 0])
product_sales = sales_df.groupby('product')['sales_amount'].sum()
product_sales.plot(kind='pie', ax=ax3, autopct='%1.1f%%')
ax3.set_title('产品销售额占比', fontsize=14)
ax3.set_ylabel('')

ax4 = fig.add_subplot(gs[1, 1])
region_sales = sales_df.groupby('region')['sales_amount'].sum()
region_sales.plot(kind='bar', ax=ax4, color='lightcoral')
ax4.set_title('区域销售额对比', fontsize=14)
ax4.tick_params(axis='x', rotation=45)

ax5 = fig.add_subplot(gs[1, 2:])
sns.boxplot(data=sales_df, x='product', y='sales_amount', ax=ax5)
ax5.set_title('各产品销售额分布', fontsize=14)
ax5.tick_params(axis='x', rotation=45)

# 第三行:员工数据分析
ax6 = fig.add_subplot(gs[2, 0])
employee_df.plot.scatter(x='age', y='salary', alpha=0.6, ax=ax6)
ax6.set_title('年龄与薪资关系', fontsize=14)

ax7 = fig.add_subplot(gs[2, 1])
dept_count = employee_df['department'].value_counts()
dept_count.plot(kind='bar', ax=ax7, color='lightgreen')
ax7.set_title('部门人数分布', fontsize=14)
ax7.tick_params(axis='x', rotation=45)

ax8 = fig.add_subplot(gs[2, 2:])
corr_matrix = employee_df[['age', 'salary', 'experience_years', 'performance_score']].corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0, ax=ax8)
ax8.set_title('员工数据相关性', fontsize=14)

plt.suptitle('综合数据分析仪表板', fontsize=16, y=0.98)
plt.show()

4. 交互式可视化

4.1 使用 Plotly 创建交互式图表

python
print("\n=== 交互式可视化示例 ===")

try:
    import plotly.express as px
    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    
    print("创建交互式图表...")
    
    # 1. 交互式散点图
    fig_scatter = px.scatter(
        employee_df, 
        x='age', 
        y='salary',
        color='department',
        size='performance_score',
        hover_data=['experience_years'],
        title='员工年龄-薪资交互式散点图'
    )
    fig_scatter.show()
    
    # 2. 交互式时间序列图
    daily_sales_df = sales_df.groupby('date')['sales_amount'].sum().reset_index()
    fig_line = px.line(
        daily_sales_df,
        x='date',
        y='sales_amount',
        title='每日销售额交互式趋势图'
    )
    fig_line.show()
    
    # 3. 交互式柱状图
    product_sales_df = sales_df.groupby('product')['sales_amount'].sum().reset_index()
    fig_bar = px.bar(
        product_sales_df,
        x='product',
        y='sales_amount',
        title='产品销售额交互式柱状图'
    )
    fig_bar.show()
    
    # 4. 交互式热力图
    fig_heatmap = px.imshow(
        corr_matrix,
        text_auto=True,
        aspect="auto",
        title='相关性交互式热力图'
    )
    fig_heatmap.show()
    
except ImportError:
    print("Plotly 未安装,跳过交互式可视化演示")
    print("可以使用 'pip install plotly' 安装 Plotly")

4.2 动态图表更新

python
# 创建动态更新的图表示例
def create_animated_chart():
    """创建动画图表"""
    try:
        import plotly.express as px
        
        # 创建月度数据
        monthly_data = []
        for month in range(1, 13):
            month_data = sales_df[sales_df['month'] == month]
            for product in month_data['product'].unique():
                product_data = month_data[month_data['product'] == product]
                monthly_data.append({
                    'month': month,
                    'product': product,
                    'total_sales': product_data['sales_amount'].sum(),
                    'avg_satisfaction': product_data['customer_satisfaction'].mean()
                })
        
        monthly_df = pd.DataFrame(monthly_data)
        
        # 创建动画散点图
        fig = px.scatter(
            monthly_df,
            x='total_sales',
            y='avg_satisfaction',
            animation_frame='month',
            color='product',
            size='total_sales',
            title='月度产品销售额与客户满意度动画图'
        )
        
        fig.show()
        
    except ImportError:
        print("需要安装 Plotly 才能创建动画图表")

# create_animated_chart()

5. 专业图表定制

5.1 图表样式定制

python
print("\n=== 图表样式定制 ===")

# 创建专业的图表样式
def create_professional_chart():
    """创建专业样式的图表"""
    
    # 设置专业配色方案
    colors = ['#2E86AB', '#A23B72', '#F18F01', '#C73E1D', '#592E83']
    
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    
    # 1. 专业柱状图
    product_sales = sales_df.groupby('product')['sales_amount'].sum().sort_values(ascending=False)
    bars = axes[0,0].bar(product_sales.index, product_sales.values, color=colors)
    axes[0,0].set_title('产品销售额排名', fontsize=16, fontweight='bold', pad=20)
    axes[0,0].set_ylabel('销售额 (万元)', fontsize=12)
    axes[0,0].tick_params(axis='x', rotation=45)
    
    # 添加数值标签
    for bar in bars:
        height = bar.get_height()
        axes[0,0].text(bar.get_x() + bar.get_width()/2., height,
                      f'{height:.0f}',
                      ha='center', va='bottom', fontsize=10)
    
    # 美化网格
    axes[0,0].grid(True, alpha=0.3, linestyle='--')
    axes[0,0].set_axisbelow(True)
    
    # 2. 专业线图
    monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
    axes[0,1].plot(monthly_sales.index, monthly_sales.values, 
                  marker='o', linewidth=3, markersize=8, color=colors[0])
    axes[0,1].fill_between(monthly_sales.index, monthly_sales.values, alpha=0.3, color=colors[0])
    axes[0,1].set_title('月度销售趋势', fontsize=16, fontweight='bold', pad=20)
    axes[0,1].set_ylabel('销售额 (万元)', fontsize=12)
    axes[0,1].set_xlabel('月份', fontsize=12)
    axes[0,1].grid(True, alpha=0.3, linestyle='--')
    axes[0,1].set_axisbelow(True)
    
    # 3. 专业散点图
    for i, dept in enumerate(employee_df['department'].unique()):
        dept_data = employee_df[employee_df['department'] == dept]
        axes[1,0].scatter(dept_data['age'], dept_data['salary'], 
                         label=dept, alpha=0.7, s=60, color=colors[i % len(colors)])
    
    axes[1,0].set_title('年龄与薪资关系分析', fontsize=16, fontweight='bold', pad=20)
    axes[1,0].set_xlabel('年龄', fontsize=12)
    axes[1,0].set_ylabel('薪资 (元)', fontsize=12)
    axes[1,0].legend(frameon=True, fancybox=True, shadow=True)
    axes[1,0].grid(True, alpha=0.3, linestyle='--')
    axes[1,0].set_axisbelow(True)
    
    # 4. 专业饼图
    region_sales = sales_df.groupby('region')['sales_amount'].sum()
    wedges, texts, autotexts = axes[1,1].pie(region_sales.values, 
                                            labels=region_sales.index,
                                            autopct='%1.1f%%',
                                            colors=colors,
                                            explode=(0.05, 0.05, 0.05, 0.05),
                                            shadow=True,
                                            startangle=90)
    
    axes[1,1].set_title('区域销售额分布', fontsize=16, fontweight='bold', pad=20)
    
    # 美化饼图文字
    for autotext in autotexts:
        autotext.set_color('white')
        autotext.set_fontweight('bold')
    
    # 调整整体布局
    plt.tight_layout()
    plt.suptitle('销售数据分析报告', fontsize=20, fontweight='bold', y=0.98)
    plt.show()

create_professional_chart()

5.2 主题和配色方案

python
print("\n=== 主题和配色方案 ===")

# 定义多种配色方案
color_schemes = {
    'business': ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd'],
    'pastel': ['#AEC7E8', '#FFBB78', '#98DF8A', '#FF9896', '#C5B0D5'],
    'dark': ['#2E3440', '#3B4252', '#434C5E', '#4C566A', '#5E81AC'],
    'vibrant': ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
}

def apply_theme(theme_name='business'):
    """应用指定主题"""
    colors = color_schemes.get(theme_name, color_schemes['business'])
    
    fig, axes = plt.subplots(2, 2, figsize=(15, 10))
    
    # 应用主题色彩
    product_sales = sales_df.groupby('product')['sales_amount'].sum()
    product_sales.plot(kind='bar', ax=axes[0,0], color=colors)
    axes[0,0].set_title(f'{theme_name.title()} 主题 - 产品销售额')
    
    region_sales = sales_df.groupby('region')['sales_amount'].sum()
    region_sales.plot(kind='pie', ax=axes[0,1], colors=colors, autopct='%1.1f%%')
    axes[0,1].set_title(f'{theme_name.title()} 主题 - 区域分布')
    
    # 多线图
    for i, product in enumerate(sales_df['product'].unique()):
        product_data = sales_df[sales_df['product'] == product]
        monthly_data = product_data.groupby('month')['sales_amount'].sum()
        axes[1,0].plot(monthly_data.index, monthly_data.values, 
                      marker='o', label=product, color=colors[i % len(colors)])
    
    axes[1,0].set_title(f'{theme_name.title()} 主题 - 月度趋势')
    axes[1,0].legend()
    axes[1,0].grid(True, alpha=0.3)
    
    # 散点图
    for i, dept in enumerate(employee_df['department'].unique()):
        dept_data = employee_df[employee_df['department'] == dept]
        axes[1,1].scatter(dept_data['age'], dept_data['salary'], 
                         label=dept, alpha=0.7, color=colors[i % len(colors)])
    
    axes[1,1].set_title(f'{theme_name.title()} 主题 - 年龄薪资')
    axes[1,1].legend()
    axes[1,1].grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()

# 展示不同主题
for theme in ['business', 'pastel', 'vibrant']:
    print(f"\n应用 {theme} 主题:")
    apply_theme(theme)

6. 数据故事讲述

6.1 创建数据故事

python
print("\n=== 数据故事讲述 ===")

def create_data_story():
    """创建完整的数据故事"""
    
    fig = plt.figure(figsize=(20, 24))
    gs = GridSpec(6, 3, figure=fig, hspace=0.4, wspace=0.3)
    
    # 标题页
    title_ax = fig.add_subplot(gs[0, :])
    title_ax.text(0.5, 0.5, '2022年度销售业绩分析报告', 
                 ha='center', va='center', fontsize=24, fontweight='bold')
    title_ax.text(0.5, 0.3, '基于Pandas数据分析的深度洞察', 
                 ha='center', va='center', fontsize=16, style='italic')
    title_ax.axis('off')
    
    # 第一部分:总体概况
    ax1 = fig.add_subplot(gs[1, 0])
    total_sales = sales_df['sales_amount'].sum()
    total_orders = len(sales_df)
    avg_order_value = total_sales / total_orders
    
    metrics = ['总销售额', '订单数量', '平均订单价值']
    values = [total_sales/10000, total_orders, avg_order_value]
    colors = ['#FF6B6B', '#4ECDC4', '#45B7D1']
    
    bars = ax1.bar(metrics, values, color=colors)
    ax1.set_title('2022年度业绩概览', fontsize=14, fontweight='bold')
    ax1.set_ylabel('数值')
    
    # 添加数值标签
    for i, (bar, value) in enumerate(zip(bars, values)):
        if i == 0:
            label = f'{value:.1f}万'
        elif i == 1:
            label = f'{value:.0f}'
        else:
            label = f'{value:.0f}元'
        ax1.text(bar.get_x() + bar.get_width()/2., bar.get_height(),
                label, ha='center', va='bottom', fontweight='bold')
    
    # 第二部分:时间趋势
    ax2 = fig.add_subplot(gs[1, 1:])
    daily_sales = sales_df.groupby('date')['sales_amount'].sum()
    monthly_avg = daily_sales.resample('M').mean()
    
    ax2.plot(daily_sales.index, daily_sales.values, alpha=0.3, color='lightblue', label='每日销售额')
    ax2.plot(monthly_avg.index, monthly_avg.values, linewidth=3, color='darkblue', 
            marker='o', markersize=8, label='月度平均')
    ax2.set_title('销售额时间趋势分析', fontsize=14, fontweight='bold')
    ax2.set_ylabel('销售额')
    ax2.legend()
    ax2.grid(True, alpha=0.3)
    
    # 第三部分:产品分析
    ax3 = fig.add_subplot(gs[2, 0])
    product_sales = sales_df.groupby('product')['sales_amount'].sum().sort_values(ascending=True)
    product_sales.plot(kind='barh', ax=ax3, color='lightcoral')
    ax3.set_title('产品销售额排名', fontsize=14, fontweight='bold')
    ax3.set_xlabel('销售额')
    
    # 第四部分:区域分析
    ax4 = fig.add_subplot(gs[2, 1])
    region_sales = sales_df.groupby('region')['sales_amount'].sum()
    wedges, texts, autotexts = ax4.pie(region_sales.values, labels=region_sales.index,
                                      autopct='%1.1f%%', startangle=90,
                                      colors=['#FF9999', '#66B2FF', '#99FF99', '#FFCC99'])
    ax4.set_title('区域销售分布', fontsize=14, fontweight='bold')
    
    # 第五部分:客户满意度分析
    ax5 = fig.add_subplot(gs[2, 2])
    satisfaction_by_product = sales_df.groupby('product')['customer_satisfaction'].mean()
    satisfaction_by_product.plot(kind='bar', ax=ax5, color='lightgreen')
    ax5.set_title('产品客户满意度', fontsize=14, fontweight='bold')
    ax5.set_ylabel('满意度评分')
    ax5.tick_params(axis='x', rotation=45)
    
    # 第六部分:相关性分析
    ax6 = fig.add_subplot(gs[3, :])
    # 创建相关性数据
    correlation_data = sales_df[['sales_amount', 'quantity', 'customer_satisfaction']].corr()
    im = ax6.imshow(correlation_data, cmap='RdBu', aspect='auto')
    ax6.set_xticks(range(len(correlation_data.columns)))
    ax6.set_yticks(range(len(correlation_data.columns)))
    ax6.set_xticklabels(correlation_data.columns)
    ax6.set_yticklabels(correlation_data.columns)
    ax6.set_title('销售指标相关性分析', fontsize=14, fontweight='bold')
    
    # 添加相关系数标注
    for i in range(len(correlation_data.columns)):
        for j in range(len(correlation_data.columns)):
            ax6.text(j, i, f'{correlation_data.iloc[i, j]:.2f}',
                    ha='center', va='center', fontweight='bold')
    
    plt.colorbar(im, ax=ax6, shrink=0.8)
    
    # 第七部分:关键洞察
    insights_ax = fig.add_subplot(gs[4, :])
    insights_text = """
    关键洞察与建议:
    
    1. 销售趋势:全年销售呈现稳定增长态势,第四季度表现尤为突出
    2. 产品表现:产品A和产品B占据主要市场份额,建议加大投入
    3. 区域分布:各区域发展相对均衡,可考虑差异化策略
    4. 客户满意度:整体满意度良好,但仍有提升空间
    5. 相关性发现:销售额与数量正相关,客户满意度影响复购率
    
    建议行动:
    • 加强产品A和B的市场推广
    • 提升客户服务质量,提高满意度
    • 优化供应链,确保产品质量稳定
    • 建立客户反馈机制,持续改进
    """
    
    insights_ax.text(0.05, 0.95, insights_text, transform=insights_ax.transAxes,
                    fontsize=12, verticalalignment='top', fontfamily='monospace',
                    bbox=dict(boxstyle='round', facecolor='lightgray', alpha=0.8))
    insights_ax.axis('off')
    
    # 第八部分:数据来源和方法
    method_ax = fig.add_subplot(gs[5, :])
    method_text = """
    数据来源与分析方法:
    • 数据来源:2022年1月1日至12月31日销售系统数据
    • 样本量:365个数据点,涵盖5个产品线和4个销售区域
    • 分析工具:Python Pandas + Matplotlib + Seaborn
    • 统计方法:描述性统计、相关性分析、趋势分析
    • 可视化:多维度图表展示,支持交互式探索
    """
    
    method_ax.text(0.05, 0.5, method_text, transform=method_ax.transAxes,
                  fontsize=10, verticalalignment='center', fontfamily='monospace',
                  bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.8))
    method_ax.axis('off')
    
    plt.suptitle('数据驱动的业务洞察报告', fontsize=20, fontweight='bold', y=0.98)
    plt.show()

create_data_story()

7. 导出和保存图表

7.1 多格式导出

python
print("\n=== 图表导出示例 ===")

import os

# 创建输出目录
output_dir = 'charts_output'
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

def export_charts():
    """导出各种格式的图表"""
    
    # 创建示例图表
    fig, ax = plt.subplots(figsize=(10, 6))
    
    monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
    monthly_sales.plot(kind='bar', ax=ax, color='skyblue')
    ax.set_title('月度销售额分析', fontsize=16, fontweight='bold')
    ax.set_ylabel('销售额')
    ax.set_xlabel('月份')
    ax.grid(True, alpha=0.3)
    
    # 导出为不同格式
    formats = ['png', 'pdf', 'svg', 'jpg']
    
    for fmt in formats:
        filename = f'{output_dir}/monthly_sales.{fmt}'
        plt.savefig(filename, format=fmt, dpi=300, bbox_inches='tight')
        print(f"图表已保存为: {filename}")
    
    plt.show()
    
    # 批量导出多个图表
    chart_configs = [
        {
            'data': sales_df.groupby('product')['sales_amount'].sum(),
            'kind': 'bar',
            'title': '产品销售额对比',
            'filename': 'product_sales'
        },
        {
            'data': sales_df.groupby('region')['sales_amount'].sum(),
            'kind': 'pie',
            'title': '区域销售分布',
            'filename': 'region_distribution'
        }
    ]
    
    for config in chart_configs:
        fig, ax = plt.subplots(figsize=(10, 6))
        
        if config['kind'] == 'bar':
            config['data'].plot(kind='bar', ax=ax, color='lightcoral')
        elif config['kind'] == 'pie':
            config['data'].plot(kind='pie', ax=ax, autopct='%1.1f%%')
            ax.set_ylabel('')
        
        ax.set_title(config['title'], fontsize=16, fontweight='bold')
        
        # 保存为PNG格式
        filename = f"{output_dir}/{config['filename']}.png"
        plt.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"图表已保存为: {filename}")
        
        plt.close()  # 关闭图表以释放内存

export_charts()

# 创建图表模板
def create_chart_template(data, chart_type, title, filename):
    """创建标准化的图表模板"""
    
    fig, ax = plt.subplots(figsize=(12, 8))
    
    # 应用统一样式
    plt.style.use('seaborn-v0_8')
    
    if chart_type == 'line':
        data.plot(kind='line', ax=ax, linewidth=3, marker='o', markersize=8)
    elif chart_type == 'bar':
        data.plot(kind='bar', ax=ax, color='#2E86AB')
    elif chart_type == 'pie':
        data.plot(kind='pie', ax=ax, autopct='%1.1f%%', startangle=90)
        ax.set_ylabel('')
    
    ax.set_title(title, fontsize=18, fontweight='bold', pad=20)
    ax.grid(True, alpha=0.3)
    
    # 添加水印
    fig.text(0.99, 0.01, 'Generated by Pandas Analytics', 
            ha='right', va='bottom', alpha=0.5, fontsize=8)
    
    # 保存图表
    plt.savefig(f'{output_dir}/{filename}.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return fig

print("\n使用图表模板:")
create_chart_template(
    sales_df.groupby('month')['sales_amount'].sum(),
    'line',
    '月度销售趋势分析',
    'monthly_trend_template'
)

8. 性能优化和最佳实践

8.1 大数据可视化优化

python
print("\n=== 大数据可视化优化 ===")

# 创建大数据集
large_sales_data = pd.concat([sales_df] * 100, ignore_index=True)
print(f"大数据集大小: {large_sales_data.shape}")

def optimize_large_data_viz(df, sample_size=1000):
    """优化大数据可视化"""
    
    import time
    
    # 方法1: 数据采样
    start_time = time.time()
    sampled_df = df.sample(n=min(sample_size, len(df)))
    sampled_df.plot.scatter(x='quantity', y='sales_amount', alpha=0.6, figsize=(10, 6))
    plt.title(f'采样可视化 (样本量: {len(sampled_df)})')
    plt.show()
    sampling_time = time.time() - start_time
    
    # 方法2: 数据聚合
    start_time = time.time()
    aggregated_df = df.groupby(['product', 'region']).agg({
        'sales_amount': 'mean',
        'quantity': 'mean',
        'customer_satisfaction': 'mean'
    }).reset_index()
    
    aggregated_df.plot.scatter(x='quantity', y='sales_amount', 
                              s=aggregated_df['customer_satisfaction']*20,
                              c='customer_satisfaction', colormap='viridis',
                              figsize=(10, 6))
    plt.title(f'聚合可视化 (数据点: {len(aggregated_df)})')
    plt.show()
    aggregation_time = time.time() - start_time
    
    print(f"采样方法耗时: {sampling_time:.3f} 秒")
    print(f"聚合方法耗时: {aggregation_time:.3f} 秒")
    
    return sampled_df, aggregated_df

sampled_data, aggregated_data = optimize_large_data_viz(large_sales_data)

8.2 内存优化技巧

python
print("\n=== 内存优化技巧 ===")

def memory_efficient_plotting():
    """内存高效的绘图方法"""
    
    # 1. 使用生成器避免创建大量中间变量
    def plot_generator(df, group_col):
        for group_name, group_data in df.groupby(group_col):
            yield group_name, group_data
    
    # 2. 分批处理大数据
    chunk_size = 1000
    fig, ax = plt.subplots(figsize=(12, 8))
    
    colors = plt.cm.Set3(np.linspace(0, 1, len(sales_df['product'].unique())))
    
    for i, (product, product_data) in enumerate(plot_generator(sales_df, 'product')):
        # 只绘制前100个点以节省内存
        sample_data = product_data.head(100)
        ax.scatter(sample_data['quantity'], sample_data['sales_amount'], 
                  label=product, alpha=0.6, color=colors[i])
    
    ax.set_title('内存优化散点图')
    ax.set_xlabel('销量')
    ax.set_ylabel('销售额')
    ax.legend()
    plt.show()
    
    # 3. 及时清理图表对象
    plt.close('all')  # 关闭所有图表
    
    # 4. 使用上下文管理器
    with plt.style.context('seaborn-v0_8'):
        fig, ax = plt.subplots(figsize=(10, 6))
        sales_df.groupby('month')['sales_amount'].sum().plot(ax=ax)
        ax.set_title('使用上下文管理器的图表')
        plt.show()
    # 样式会自动恢复

memory_efficient_plotting()

9. 可视化最佳实践

9.1 图表选择指南

python
print("\n=== 图表选择指南 ===")

def chart_selection_guide()

9.2 可视化设计原则

python
print("\n=== 可视化设计原则 ===")

def visualization_principles():
    """可视化设计原则示例"""
    
    principles = {
        "简洁性原则": "避免不必要的装饰,突出数据本身",
        "准确性原则": "确保图表准确反映数据,避免误导",
        "一致性原则": "保持颜色、字体、样式的一致性",
        "可读性原则": "确保标签、图例清晰可读",
        "目的性原则": "根据分析目的选择合适的图表类型"
    }
    
    print("可视化设计五大原则:")
    for principle, description in principles.items():
        print(f"• {principle}: {description}")
    
    # 好的设计示例
    fig, axes = plt.subplots(1, 2, figsize=(15, 6))
    
    # 好的设计
    monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
    axes[0].plot(monthly_sales.index, monthly_sales.values, 
                linewidth=2, marker='o', markersize=6, color='#2E86AB')
    axes[0].set_title('月度销售趋势', fontsize=14, fontweight='bold', pad=15)
    axes[0].set_xlabel('月份', fontsize=12)
    axes[0].set_ylabel('销售额 (万元)', fontsize=12)
    axes[0].grid(True, alpha=0.3, linestyle='--')
    axes[0].set_axisbelow(True)
    
    # 添加数据标签
    for i, v in enumerate(monthly_sales.values):
        if i % 2 == 0:  # 只显示部分标签避免拥挤
            axes[0].annotate(f'{v:.0f}', (monthly_sales.index[i], v), 
                           textcoords="offset points", xytext=(0,10), ha='center')
    
    axes[0].text(0.02, 0.98, '✓ 好的设计', transform=axes[0].transAxes, 
                fontsize=12, fontweight='bold', color='green',
                verticalalignment='top', bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.3))
    
    # 不好的设计示例
    axes[1].plot(monthly_sales.index, monthly_sales.values, 
                linewidth=5, marker='s', markersize=12, color='red')
    axes[1].set_title('MONTHLY SALES TREND!!!', fontsize=16, color='red')
    axes[1].set_facecolor('yellow')
    axes[1].grid(True, alpha=0.8, linewidth=2, color='blue')
    
    # 添加过多装饰
    for i, v in enumerate(monthly_sales.values):
        axes[1].annotate(f'{v:.2f}万元', (monthly_sales.index[i], v), 
                        textcoords="offset points", xytext=(0,15), ha='center',
                        fontsize=8, rotation=45)
    
    axes[1].text(0.02, 0.98, '✗ 不好的设计', transform=axes[1].transAxes, 
                fontsize=12, fontweight='bold', color='red',
                verticalalignment='top', bbox=dict(boxstyle='round', facecolor='lightcoral', alpha=0.3))
    
    plt.tight_layout()
    plt.show()

visualization_principles()

9.3 常见错误和解决方案

python
print("\n=== 常见可视化错误 ===")

def common_mistakes_and_solutions():
    """常见可视化错误及解决方案"""
    
    mistakes = {
        "错误1: 使用不合适的图表类型": {
            "问题": "用饼图显示时间序列数据",
            "解决方案": "时间序列数据应使用线图"
        },
        "错误2: 颜色使用不当": {
            "问题": "使用过多颜色或颜色对比度不够",
            "解决方案": "使用色盲友好的配色方案"
        },
        "错误3: 坐标轴问题": {
            "问题": "Y轴不从0开始,夸大差异",
            "解决方案": "合理设置坐标轴范围"
        },
        "错误4: 信息过载": {
            "问题": "在一个图表中显示过多信息",
            "解决方案": "分解为多个简单图表"
        },
        "错误5: 缺少标签和说明": {
            "问题": "图表缺少标题、轴标签或图例",
            "解决方案": "添加完整的标签和说明"
        }
    }
    
    print("常见可视化错误及解决方案:")
    for mistake, details in mistakes.items():
        print(f"\n{mistake}")
        print(f"  问题: {details['问题']}")
        print(f"  解决方案: {details['解决方案']}")
    
    # 错误示例对比
    fig, axes = plt.subplots(2, 2, figsize=(15, 10))
    
    # 错误1: 坐标轴不从0开始
    monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
    axes[0,0].plot(monthly_sales.index, monthly_sales.values, marker='o')
    axes[0,0].set_ylim(monthly_sales.min() * 0.9, monthly_sales.max() * 1.1)
    axes[0,0].set_title('错误:Y轴不从0开始')
    axes[0,0].text(0.02, 0.98, '✗ 夸大了差异', transform=axes[0,0].transAxes, 
                  fontsize=10, color='red', verticalalignment='top')
    
    # 正确1: 坐标轴从0开始
    axes[0,1].plot(monthly_sales.index, monthly_sales.values, marker='o')
    axes[0,1].set_ylim(0, monthly_sales.max() * 1.1)
    axes[0,1].set_title('正确:Y轴从0开始')
    axes[0,1].text(0.02, 0.98, '✓ 真实反映差异', transform=axes[0,1].transAxes, 
                  fontsize=10, color='green', verticalalignment='top')
    
    # 错误2: 颜色过多
    product_sales = sales_df.groupby('product')['sales_amount'].sum()
    colors_bad = ['red', 'blue', 'yellow', 'purple', 'orange']
    product_sales.plot(kind='bar', ax=axes[1,0], color=colors_bad)
    axes[1,0].set_title('错误:颜色过多且刺眼')
    axes[1,0].tick_params(axis='x', rotation=45)
    
    # 正确2: 统一配色
    colors_good = ['#2E86AB'] * len(product_sales)
    product_sales.plot(kind='bar', ax=axes[1,1], color=colors_good)
    axes[1,1].set_title('正确:统一配色方案')
    axes[1,1].tick_params(axis='x', rotation=45)
    
    plt.tight_layout()
    plt.show()

common_mistakes_and_solutions()

10. 实际应用案例

10.1 商业报告可视化

python
print("\n=== 商业报告可视化案例 ===")

def create_business_report():
    """创建完整的商业报告"""
    
    # 设置报告样式
    plt.style.use('seaborn-v0_8-whitegrid')
    
    fig = plt.figure(figsize=(16, 20))
    gs = GridSpec(5, 2, figure=fig, hspace=0.4, wspace=0.3)
    
    # 报告标题
    title_ax = fig.add_subplot(gs[0, :])
    title_ax.text(0.5, 0.7, '2022年度业务分析报告', 
                 ha='center', va='center', fontsize=24, fontweight='bold')
    title_ax.text(0.5, 0.3, f'报告生成时间: {datetime.now().strftime("%Y-%m-%d %H:%M")}', 
                 ha='center', va='center', fontsize=12, style='italic')
    title_ax.axis('off')
    
    # 1. 销售趋势分析
    ax1 = fig.add_subplot(gs[1, :])
    daily_sales = sales_df.groupby('date')['sales_amount'].sum()
    monthly_avg = daily_sales.resample('M').mean()
    
    ax1.plot(daily_sales.index, daily_sales.values, alpha=0.3, color='lightblue', label='每日销售')
    ax1.plot(monthly_avg.index, monthly_avg.values, linewidth=3, color='darkblue', 
            marker='o', markersize=8, label='月度平均')
    ax1.fill_between(monthly_avg.index, monthly_avg.values, alpha=0.2, color='darkblue')
    ax1.set_title('销售趋势分析', fontsize=16, fontweight='bold', pad=20)
    ax1.set_ylabel('销售额 (元)')
    ax1.legend()
    ax1.grid(True, alpha=0.3)
    
    # 2. 产品表现对比
    ax2 = fig.add_subplot(gs[2, 0])
    product_metrics = sales_df.groupby('product').agg({
        'sales_amount': 'sum',
        'quantity': 'sum',
        'customer_satisfaction': 'mean'
    })
    
    bars = ax2.bar(product_metrics.index, product_metrics['sales_amount'], 
                  color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'])
    ax2.set_title('产品销售额对比', fontsize=14, fontweight='bold')
    ax2.set_ylabel('销售额 (元)')
    ax2.tick_params(axis='x', rotation=45)
    
    # 添加数值标签
    for bar in bars:
        height = bar.get_height()
        ax2.text(bar.get_x() + bar.get_width()/2., height,
                f'{height:.0f}', ha='center', va='bottom')
    
    # 3. 区域分布
    ax3 = fig.add_subplot(gs[2, 1])
    region_sales = sales_df.groupby('region')['sales_amount'].sum()
    wedges, texts, autotexts = ax3.pie(region_sales.values, labels=region_sales.index,
                                      autopct='%1.1f%%', startangle=90,
                                      colors=['#FF9999', '#66B2FF', '#99FF99', '#FFCC99'])
    ax3.set_title('区域销售分布', fontsize=14, fontweight='bold')
    
    # 4. 客户满意度分析
    ax4 = fig.add_subplot(gs[3, 0])
    satisfaction_by_product = sales_df.groupby('product')['customer_satisfaction'].mean()
    bars = ax4.barh(satisfaction_by_product.index, satisfaction_by_product.values, 
                   color='lightgreen')
    ax4.set_title('产品客户满意度', fontsize=14, fontweight='bold')
    ax4.set_xlabel('满意度评分')
    
    # 添加满意度等级线
    ax4.axvline(x=4.0, color='orange', linestyle='--', alpha=0.7, label='良好线')
    ax4.axvline(x=4.5, color='green', linestyle='--', alpha=0.7, label='优秀线')
    ax4.legend()
    
    # 5. 关键指标总结
    ax5 = fig.add_subplot(gs[3, 1])
    
    # 计算关键指标
    total_revenue = sales_df['sales_amount'].sum()
    total_orders = len(sales_df)
    avg_order_value = total_revenue / total_orders
    best_product = sales_df.groupby('product')['sales_amount'].sum().idxmax()
    best_region = sales_df.groupby('region')['sales_amount'].sum().idxmax()
    
    metrics_text = f"""
    关键业务指标
    
    总收入: {total_revenue:,.0f}
    订单总数: {total_orders:,}
    平均订单价值: {avg_order_value:.0f}
    
    最佳产品: {best_product}
    最佳区域: {best_region}
    
    平均客户满意度: {sales_df['customer_satisfaction'].mean():.2f}/5.0
    """
    
    ax5.text(0.1, 0.9, metrics_text, transform=ax5.transAxes,
            fontsize=12, verticalalignment='top', fontfamily='monospace',
            bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.3))
    ax5.axis('off')
    
    # 6. 建议和结论
    ax6 = fig.add_subplot(gs[4, :])
    recommendations = """
    业务建议与行动计划:
    
    1. 产品策略: 加大对表现优异产品的投入,考虑扩大生产规模
    2. 区域发展: 在表现较弱的区域加强市场推广和渠道建设
    3. 客户体验: 持续提升客户满意度,建立客户反馈机制
    4. 销售优化: 分析销售波动原因,制定更稳定的销售策略
    5. 数据驱动: 建立定期数据分析机制,及时调整业务策略
    
    下一步行动:
    • 深入分析客户细分和购买行为
    • 建立预测模型,提前识别市场趋势
    • 优化供应链,提高运营效率
    """
    
    ax6.text(0.05, 0.95, recommendations, transform=ax6.transAxes,
            fontsize=11, verticalalignment='top',
            bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.5))
    ax6.axis('off')
    
    plt.suptitle('数据驱动的业务洞察', fontsize=18, fontweight='bold', y=0.98)
    plt.show()

create_business_report()

本章小结

本章全面介绍了 Pandas 的数据可视化功能:

核心内容回顾

  1. 基础图表类型:线图、柱状图、散点图、直方图等
  2. 高级图表:箱线图、热力图、多子图布局
  3. 交互式可视化:使用 Plotly 创建动态图表
  4. 专业定制:样式设计、主题配色、图表模板
  5. 数据故事:创建完整的分析报告和业务洞察

关键技能

  • 根据数据类型选择合适的图表
  • 使用 Pandas 内置绘图功能快速可视化
  • 结合 matplotlib 和 seaborn 创建专业图表
  • 优化大数据可视化性能
  • 遵循可视化设计原则

最佳实践

  • 保持图表简洁明了
  • 选择合适的颜色和样式
  • 添加必要的标签和说明
  • 考虑目标受众的需求
  • 用数据讲述有意义的故事

实际应用

  • 业务报告和仪表板
  • 数据探索和分析
  • 学术研究和论文
  • 产品分析和用户洞察
  • 市场研究和竞争分析

掌握这些可视化技能,能够帮助你:

  • 快速发现数据中的模式和趋势
  • 有效传达分析结果和洞察
  • 制作专业的数据报告
  • 支持数据驱动的决策制定

练习题

  1. 创建一个包含多种图表类型的综合仪表板
  2. 设计一个交互式的销售分析工具
  3. 制作一份完整的数据分析报告
  4. 优化大数据集的可视化性能
  5. 开发一套标准化的图表模板

下一章我们将学习 Pandas 的高级功能,探索更复杂的数据处理和分析技术。: """图表选择指南和示例"""

guide = {
    "比较数值": {
        "适用图表": ["柱状图", "条形图", "雷达图"],
        "示例": "各产品销售额对比"
    },
    "显示趋势": {
        "适用图表": ["线图", "面积图"],
        "示例": "月度销售趋势"
    },
    "显示分布": {
        "适用图表": ["直方图", "箱线图", "小提琴图"],
        "示例": "员工薪资分布"
    },
    "显示关系": {
        "适用图表": ["散点图", "气泡图", "热力图"],
        "示例": "年龄与薪资关系"
    },
    "显示构成": {
        "适用图表": ["饼图", "堆叠柱状图", "树状图"],
        "示例": "区域销售占比"
    }
}

print("图表选择指南:")
for purpose, info in guide.items():
    print(f"\n{purpose}:")
    print(f"  推荐图表: {', '.join(info['适用图表'])}")
    print(f"  应用示例: {info['示例']}")

# 创建对比示例
fig, axes = plt.subplots(2, 3, figsize=(18, 12))

# 1. 比较 - 柱状图
product_sales = sales_df.groupby('product')['sales_amount'].sum()
product_sales.plot(kind='bar', ax=axes[0,0], color='skyblue')
axes[0,0].set_title('比较:产品销售额')
axes[0,0].tick_params(axis='x', rotation=45)

# 2. 趋势 - 线图
monthly_sales = sales_df.groupby('month')['sales_amount'].sum()
monthly_sales.plot(kind='line', ax=axes[0,1], marker='o', color='red')
axes[0,1].set_title('趋势:月度销售额')
axes[0,1].grid(True, alpha=0.3)

# 3. 分布 - 直方图
employee_df['salary'].plot.hist(bins=30, ax=axes[0,2], alpha=0.7, color='green')
axes[0,2].set_title('分布:薪资分布')
axes[0,2].set_xlabel('薪资')

# 4. 关系 - 散点图
employee_df.plot.scatter(x='age', y='salary', ax=axes[1,0], alpha=0.6, color='purple')
axes[1,0].set_title('关系:年龄与薪资')

# 5. 构成 - 饼图
region_sales = sales_df.groupby('region')['sales_amount'].sum()
region_sales.plot(kind='pie', ax=axes[1,1], autopct='%1.1f%%')
axes[1,1].set_title('构成:区域销售占比')
axes[1,1].set_ylabel('')

# 6. 相关性 - 热力图
corr_data = employee_df[['age', 'salary', 'experience_years', 'performance_score']].corr()
im = axes[1,2].imshow(corr_data, cmap='coolwarm', aspect='auto')
axes[1,2].set_title('相关性:员工数据热力图')
axes[1,2].set_xticks(range(len(corr_data.columns)))
axes[1,2].set_yticks(range(len(corr_data.columns)))
axes[1,2].set_xticklabels(corr_data.columns, rotation=45)
axes[1,2].set_yticklabels(corr_data.columns)

plt.tight_layout()
plt.show()

chart_selection_guide()