python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python可视化库Matplotlib与Seaborn

Python可视化库Matplotlib与Seaborn的使用方法

作者:YuG819

本文系统讲解Python两大核心可视化库Matplotlib与Seaborn的使用方法,从基础图表绘制到高级定制化,通过真实数据集实战演示折线图、柱状图、散点图、热力图、箱线图等常用图表的绘制技巧,帮助读者快速掌握数据可视化的核心能力,需要的朋友可以参考下

一、前言

数据可视化是数据分析流程中至关重要的一环。再精准的数据分析结论,如果不能通过直观的图表呈现出来,其价值将大打折扣。

Python可视化生态中,Matplotlib是最基础的绘图库,提供了完全的控制能力;Seaborn则基于Matplotlib封装,专注于统计图表,能用更少的代码绘制出更美观的图表。

本文将从零开始,带你掌握这两大库的核心用法。

二、环境配置与库安装

2.1 安装依赖

pip install matplotlib seaborn pandas numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

2.2 导入库与基础配置

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 设置显示选项
plt.rcParams['axes.unicode_minus'] = False

# Seaborn风格设置
sns.set_style("whitegrid")  # 可选: darkgrid, whitegrid, dark, white, ticks
sns.set_palette("husl")     # 设置配色方案

三、Matplotlib基础绘图

3.1 第一个图表:折线图

import matplotlib.pyplot as plt
import numpy as np

# 生成数据
months = np.arange(1, 13)
temperature = np.array([15, 18, 25, 32, 38, 42, 45, 43, 38, 30, 22, 17])

# 创建图表
plt.figure(figsize=(10, 6))
plt.plot(months, temperature, marker='o', linewidth=2, markersize=8, color='#FF6B6B')

# 添加标题和标签
plt.title('Monthly Average Temperature Trend 2024', fontsize=16, fontweight='bold', pad=20)
plt.xlabel('Month', fontsize=12)
plt.ylabel('Temperature (°C)', fontsize=12)

# 设置x轴刻度
month_labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
plt.xticks(months, month_labels)

# 添加网格线
plt.grid(True, alpha=0.3, linestyle='--')

# 标注最高温和最低温
max_idx = np.argmax(temperature)
min_idx = np.argmin(temperature)
plt.annotate(f'Max: {temperature[max_idx]}°C', xy=(months[max_idx], temperature[max_idx]),
             xytext=(months[max_idx]-1, temperature[max_idx]+3),
             arrowprops=dict(arrowstyle='->', color='red'))
plt.annotate(f'Min: {temperature[min_idx]}°C', xy=(months[min_idx], temperature[min_idx]),
             xytext=(months[min_idx]+1, temperature[min_idx]-5),
             arrowprops=dict(arrowstyle='->', color='blue'))

plt.tight_layout()
plt.savefig('temperature_trend.png', dpi=150, bbox_inches='tight')
plt.show()

3.2 图表组成元素详解

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

# 绘制多条线
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label='sin(x)', color='#4ECDC4', linewidth=2)
ax.plot(x, np.cos(x), label='cos(x)', color='#FF6B6B', linewidth=2, linestyle='--')

# 设置标题和标签
ax.set_title('Trigonometric Functions', fontsize=14, pad=15)
ax.set_xlabel('X Axis (radians)', fontsize=12)
ax.set_ylabel('Y Axis (function value)', fontsize=12)

# 设置坐标轴范围
ax.set_xlim(0, 10)
ax.set_ylim(-1.5, 1.5)

# 添加图例
ax.legend(loc='upper right', frameon=True, shadow=True)

# 添加水平参考线
ax.axhline(y=0, color='black', linewidth=0.5)
ax.axvline(x=np.pi, color='gray', linestyle=':', alpha=0.7)

# 设置刻度样式
ax.tick_params(axis='both', which='major', labelsize=10)

# 添加文字注释
ax.text(5, 1.2, 'Sine and Cosine Functions', fontsize=12, ha='center',
        bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))

plt.tight_layout()
plt.show()

3.3 多子图布局

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

# 子图1:折线图
x = np.arange(5)
sales = [120, 150, 180, 165, 200]
axes[0, 0].plot(x, sales, marker='s', color='steelblue')
axes[0, 0].set_title('Sales Trend')
axes[0, 0].set_xticks(x)
axes[0, 0].set_xticklabels(['Q1', 'Q2', 'Q3', 'Q4', 'Q5'])

# 子图2:柱状图
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]
axes[0, 1].bar(categories, values, color='coral')
axes[0, 1].set_title('Product Sales Comparison')

# 子图3:散点图
np.random.seed(42)
x_scatter = np.random.randn(50)
y_scatter = np.random.randn(50)
axes[1, 0].scatter(x_scatter, y_scatter, alpha=0.6, c=y_scatter, cmap='viridis')
axes[1, 0].set_title('Scatter Distribution')

# 子图4:饼图
sizes = [30, 25, 20, 15, 10]
labels = ['Phone', 'PC', 'Tablet', 'Accessory', 'Other']
axes[1, 1].pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90)
axes[1, 1].set_title('Category Proportion')

plt.suptitle('Data Visualization Dashboard', fontsize=16, fontweight='bold', y=1.02)
plt.tight_layout()
plt.show()

四、常用图表类型实战

4.1 柱状图与条形图

# 分组柱状图:各部门季度业绩
departments = ['Tech', 'Product', 'Ops', 'Marketing', 'Support']
q1 = [85, 72, 90, 68, 75]
q2 = [88, 78, 85, 75, 80]
q3 = [92, 85, 88, 82, 78]
q4 = [95, 90, 92, 88, 85]

x = np.arange(len(departments))
width = 0.2

fig, ax = plt.subplots(figsize=(12, 6))
ax.bar(x - 1.5*width, q1, width, label='Q1', color='#FF6B6B')
ax.bar(x - 0.5*width, q2, width, label='Q2', color='#4ECDC4')
ax.bar(x + 0.5*width, q3, width, label='Q3', color='#45B7D1')
ax.bar(x + 1.5*width, q4, width, label='Q4', color='#96CEB4')

ax.set_xlabel('Department', fontsize=12)
ax.set_ylabel('Performance Score', fontsize=12)
ax.set_title('Quarterly Performance by Department', fontsize=14, fontweight='bold')
ax.set_xticks(x)
ax.set_xticklabels(departments)
ax.legend()
ax.set_ylim(0, 110)

# 添加数值标签
for i, v in enumerate(q4):
    ax.text(i + 1.5*width, v + 1, str(v), ha='center', fontsize=9)

plt.tight_layout()
plt.show()

4.2 散点图与气泡图

# 气泡图:展示销售额、利润率和市场份额的关系
np.random.seed(42)
n = 30
sales = np.random.randint(50, 500, n)
profit_margin = np.random.uniform(5, 35, n)
market_share = np.random.uniform(1, 20, n)  # 气泡大小
categories = np.random.choice(['Type A', 'Type B', 'Type C'], n)

colors = {'Type A': '#FF6B6B', 'Type B': '#4ECDC4', 'Type C': '#45B7D1'}

fig, ax = plt.subplots(figsize=(10, 7))
for cat in ['Type A', 'Type B', 'Type C']:
    mask = categories == cat
    ax.scatter(sales[mask], profit_margin[mask], 
               s=market_share[mask]*30, 
               c=colors[cat], alpha=0.6, label=cat, edgecolors='black', linewidth=0.5)

ax.set_xlabel('Sales (10K CNY)', fontsize=12)
ax.set_ylabel('Profit Margin (%)', fontsize=12)
ax.set_title('Sales vs Profit Margin Analysis (Bubble size = Market Share)', fontsize=14)
ax.legend(title='Product Category')
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

4.3 饼图与环形图

# 环形图
labels = ['Mobile', 'PC', 'MiniApp', 'H5', 'Other']
sizes = [45, 25, 15, 10, 5]
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
explode = (0.05, 0, 0, 0, 0)

fig, ax = plt.subplots(figsize=(8, 8))
wedges, texts, autotexts = ax.pie(sizes, labels=labels, colors=colors,
                                   autopct='%1.1f%%', startangle=90,
                                   explode=explode, pctdistance=0.85,
                                   wedgeprops=dict(width=0.5, edgecolor='white'))

# 中心文字
ax.text(0, 0, 'Traffic Source\nDistribution', ha='center', va='center', fontsize=14, fontweight='bold')

ax.set_title('Q3 2024 Traffic Source Distribution', fontsize=14, pad=20)
plt.setp(autotexts, size=10, weight='bold')
plt.tight_layout()
plt.show()

4.4 直方图与密度图

np.random.seed(42)
data_a = np.random.normal(100, 15, 1000)
data_b = np.random.normal(130, 20, 1000)

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

# 直方图
axes[0].hist(data_a, bins=30, alpha=0.7, label='Group A', color='#FF6B6B', edgecolor='black')
axes[0].hist(data_b, bins=30, alpha=0.7, label='Group B', color='#4ECDC4', edgecolor='black')
axes[0].set_xlabel('Value')
axes[0].set_ylabel('Frequency')
axes[0].set_title('Histogram of Data Distribution')
axes[0].legend()

# 密度图
axes[1].hist(data_a, bins=30, density=True, alpha=0.5, color='#FF6B6B', label='Group A')
axes[1].hist(data_b, bins=30, density=True, alpha=0.5, color='#4ECDC4', label='Group B')
axes[1].set_xlabel('Value')
axes[1].set_ylabel('Density')
axes[1].set_title('Density Plot of Data Distribution')
axes[1].legend()

plt.tight_layout()
plt.show()

五、Seaborn高级可视化

5.1 Seaborn简介与风格设置

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 加载示例数据集
tips = sns.load_dataset('tips')
print(tips.head())

# 设置全局风格
sns.set_theme(style="whitegrid", palette="pastel", font_scale=1.1)

5.2 分类数据可视化

# 箱线图:展示不同日期的小费分布
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

sns.boxplot(data=tips, x='day', y='total_bill', hue='sex', ax=axes[0])
axes[0].set_title('Daily Total Bill Distribution (Box Plot)')
axes[0].set_xlabel('Day')
axes[0].set_ylabel('Total Bill ($)')

# 小提琴图
sns.violinplot(data=tips, x='day', y='total_bill', hue='sex', split=True, ax=axes[1])
axes[1].set_title('Daily Total Bill Distribution (Violin Plot)')
axes[1].set_xlabel('Day')
axes[1].set_ylabel('Total Bill ($)')

plt.tight_layout()
plt.show()

5.3 分布数据可视化

# 联合分布图
sns.jointplot(data=tips, x='total_bill', y='tip', kind='reg', 
              height=8, color='#4ECDC4')
plt.suptitle('Relationship between Total Bill and Tip', y=1.02, fontsize=14)
plt.show()

# 配对图
iris = sns.load_dataset('iris')
sns.pairplot(iris, hue='species', height=2.5, palette='husl')
plt.suptitle('Iris Dataset Pairwise Analysis', y=1.02, fontsize=14)
plt.show()

5.4 相关性热力图

# 构造相关性数据
np.random.seed(42)
df_corr = pd.DataFrame({
    'sales': np.random.randint(100, 1000, 100),
    'ad_spend': np.random.randint(20, 200, 100),
    'customers': np.random.randint(50, 500, 100),
    'return_rate': np.random.uniform(0.01, 0.15, 100),
    'satisfaction': np.random.uniform(3.5, 5.0, 100)
})

# 添加相关性
df_corr['profit'] = df_corr['sales'] * 0.3 + np.random.normal(0, 20, 100)
df_corr['repurchase'] = df_corr['satisfaction'] * 0.1 + np.random.normal(0, 0.05, 100)

# 计算相关系数矩阵
corr_matrix = df_corr.corr()

fig, ax = plt.subplots(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='RdYlBu_r',
            center=0, square=True, linewidths=0.5, cbar_kws={"shrink": 0.8}, ax=ax)
ax.set_title('Business Metrics Correlation Heatmap', fontsize=14, fontweight='bold', pad=20)
plt.tight_layout()
plt.show()

六、图表美化与导出

6.1 自定义配色方案

# 自定义颜色映射
from matplotlib.colors import LinearSegmentedColormap

colors = ['#FF6B6B', '#FFE66D', '#4ECDC4', '#45B7D1', '#96CEB4']
cmap = LinearSegmentedColormap.from_list('custom', colors)

# 使用自定义配色
fig, ax = plt.subplots(figsize=(8, 6))
data = np.random.rand(10, 10)
im = ax.imshow(data, cmap=cmap)
ax.set_title('Custom Color Heatmap')
plt.colorbar(im, ax=ax)
plt.show()

6.2 图表导出设置

注意:plt.savefig() 必须在图表创建之后、plt.show() 之前调用,否则导出的文件会是空白的。

import matplotlib.pyplot as plt
import numpy as np

# 1. 先创建图表
fig, ax = plt.subplots(figsize=(8, 6))
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label='sin(x)', color='#4ECDC4', linewidth=2)
ax.plot(x, np.cos(x), label='cos(x)', color='#FF6B6B', linewidth=2, linestyle='--')
ax.set_title('Export Demo Chart')
ax.legend()
ax.grid(True, alpha=0.3)

# 2. 再导出(在 show() 之前!)
plt.savefig('high_quality_chart.png', dpi=300, bbox_inches='tight',
            facecolor='white', edgecolor='none')

plt.savefig('vector_chart.pdf', format='pdf', bbox_inches='tight')

plt.savefig('web_chart.svg', format='svg', bbox_inches='tight')

# 3. 最后显示
plt.show()

七、综合实战:销售数据可视化大屏

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 生成模拟销售数据
np.random.seed(2024)
dates = pd.date_range('2024-01-01', '2024-12-31', freq='D')
n = len(dates)

sales_data = pd.DataFrame({
    'date': dates,
    'sales': np.random.normal(50000, 15000, n).clip(10000, 100000),
    'orders': np.random.poisson(200, n),
    'avg_price': np.random.normal(250, 50, n).clip(100, 500),
    'return_rate': np.random.uniform(0.02, 0.12, n),
    'category': np.random.choice(['Electronics', 'Clothing', 'Food', 'Home', 'Beauty'], n),
    'region': np.random.choice(['East', 'North', 'South', 'Southwest', 'Northwest'], n)
})

# 添加月份列
sales_data['month'] = sales_data['date'].dt.month
sales_data['weekday'] = sales_data['date'].dt.day_name()

# 创建大屏布局
fig = plt.figure(figsize=(16, 12))
fig.suptitle('2024 Annual Sales Data Visualization Dashboard', fontsize=20, fontweight='bold', y=0.98)

# 1. 月度销售额趋势(大图)
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=2)
monthly_sales = sales_data.groupby('month')['sales'].sum() / 10000
ax1.plot(monthly_sales.index, monthly_sales.values, marker='o', linewidth=3,
         markersize=8, color='#FF6B6B')
ax1.fill_between(monthly_sales.index, monthly_sales.values, alpha=0.3, color='#FF6B6B')
ax1.set_title('Monthly Sales Trend (10K CNY)', fontsize=13, fontweight='bold')
ax1.set_xlabel('Month')
ax1.set_ylabel('Sales')
ax1.grid(True, alpha=0.3)
for i, v in enumerate(monthly_sales.values):
    ax1.text(i+1, v+5, f'{v:.0f}', ha='center', fontsize=9)

# 2. 品类占比饼图
ax2 = plt.subplot2grid((3, 3), (0, 2))
category_sales = sales_data.groupby('category')['sales'].sum()
colors_pie = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
ax2.pie(category_sales.values, labels=category_sales.index, autopct='%1.1f%%',
        colors=colors_pie, startangle=90)
ax2.set_title('Sales Share by Category', fontsize=13, fontweight='bold')

# 3. 地区销售额柱状图
ax3 = plt.subplot2grid((3, 3), (1, 0))
region_sales = sales_data.groupby('region')['sales'].sum() / 10000
bars = ax3.bar(region_sales.index, region_sales.values, color=colors_pie[:5])
ax3.set_title('Regional Sales (10K CNY)', fontsize=13, fontweight='bold')
ax3.set_ylabel('Sales')
for bar in bars:
    height = bar.get_height()
    ax3.text(bar.get_x() + bar.get_width()/2., height,
             f'{height:.0f}', ha='center', va='bottom', fontsize=9)

# 4. 订单量与客单价散点图
ax4 = plt.subplot2grid((3, 3), (1, 1))
sample = sales_data.sample(min(500, len(sales_data)))
scatter = ax4.scatter(sample['orders'], sample['avg_price'], 
                      c=sample['sales'], cmap='YlOrRd', alpha=0.6, s=30)
ax4.set_title('Orders vs Average Price', fontsize=13, fontweight='bold')
ax4.set_xlabel('Orders')
ax4.set_ylabel('Avg Price')
plt.colorbar(scatter, ax=ax4, label='Sales')

# 5. 退货率箱线图
ax5 = plt.subplot2grid((3, 3), (1, 2))
sns.boxplot(data=sales_data, x='category', y='return_rate', hue='category', ax=ax5, palette='Set2', legend=False)
ax5.set_title('Return Rate by Category', fontsize=13, fontweight='bold')
ax5.tick_params(axis='x', rotation=45)

# 6. 星期销售热力图
ax6 = plt.subplot2grid((3, 3), (2, 0), colspan=2)
pivot_week = sales_data.pivot_table(values='sales', index='category', 
                                     columns='weekday', aggfunc='mean')
# 重新排序星期
week_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
pivot_week = pivot_week.reindex(columns=week_order)
sns.heatmap(pivot_week/1000, annot=True, fmt='.0f', cmap='YlOrRd', ax=ax6)
ax6.set_title('Weekly Sales Heatmap by Category (1K CNY)', fontsize=13, fontweight='bold')
ax6.set_xlabel('')

# 7. KPI指标卡
ax7 = plt.subplot2grid((3, 3), (2, 2))
ax7.axis('off')

total_sales = sales_data['sales'].sum() / 10000
total_orders = sales_data['orders'].sum()
avg_price = sales_data['avg_price'].mean()
avg_return = sales_data['return_rate'].mean() * 100

kpi_lines = [
    "="*22,
    "   KPI Dashboard",
    "="*22,
    "",
    f"  Total Sales: {total_sales:,.0f} (10K)",
    f"  Total Orders: {total_orders:,}",
    f"  Avg Price: {avg_price:.0f} CNY",
    f"  Avg Return: {avg_return:.2f}%",
    "",
    "="*22
]
kpi_text = "\n".join(kpi_lines)

ax7.text(0.5, 0.5, kpi_text, transform=ax7.transAxes, fontsize=12,
         verticalalignment='center', horizontalalignment='center',
         bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.3),
         family='monospace')

plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.savefig('sales_dashboard.png', dpi=150, bbox_inches='tight', facecolor='white')
plt.show()

print("\n=== Data Summary ===")
print(f"Annual Total Sales: {total_sales:,.0f} (10K CNY)")
print(f"Annual Total Orders: {total_orders:,}")
print(f"Average Price: {avg_price:.0f} CNY")
print(f"Average Return Rate: {avg_return:.2f}%")

八、总结与学习资源

核心知识点回顾

图表类型Matplotlib方法Seaborn方法适用场景
折线图plt.plot()sns.lineplot()趋势变化
柱状图plt.bar()sns.barplot()分类对比
散点图plt.scatter()sns.scatterplot()相关性分析
箱线图plt.boxplot()sns.boxplot()分布异常检测
热力图plt.imshow()sns.heatmap()矩阵相关性
直方图plt.hist()sns.histplot()数据分布
小提琴图-sns.violinplot()分布形状对比
配对图-sns.pairplot()多变量关系

学习建议

  1. 先掌握Matplotlib:理解图表的底层构造(Figure、Axes、Axis)
  2. 再用Seaborn提升效率:快速绘制统计图表
  3. 多实践真实数据:Kaggle数据集、UCI机器学习仓库
  4. 关注配色与排版:参考《The Visual Display of Quantitative Information》

写在最后:好的可视化不是堆砌图表,而是用最适合的形式讲清楚数据背后的故事。建议读者多观察优秀的数据新闻,学习如何用图表传递信息。

以上就是Python可视化库Matplotlib与Seaborn的使用方法的详细内容,更多关于Python可视化库Matplotlib与Seaborn的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文