Pandas 数据可视化

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

1. 可视化基础设置

1.1 环境配置

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 创建示例数据集

# 设置随机种子
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)

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)

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)

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 直方图和密度图

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)

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)

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 多子图布局

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 创建交互式图表

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 动态图表更新

# 创建动态更新的图表示例
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 图表样式定制

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 主题和配色方案

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 创建数据故事

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 多格式导出

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 大数据可视化优化

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 内存优化技巧

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 图表选择指南

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

def chart_selection_guide()

9.2 可视化设计原则

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 常见错误和解决方案

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 商业报告可视化

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()