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() | 多变量关系 |
学习建议
- 先掌握Matplotlib:理解图表的底层构造(Figure、Axes、Axis)
- 再用Seaborn提升效率:快速绘制统计图表
- 多实践真实数据:Kaggle数据集、UCI机器学习仓库
- 关注配色与排版:参考《The Visual Display of Quantitative Information》
写在最后:好的可视化不是堆砌图表,而是用最适合的形式讲清楚数据背后的故事。建议读者多观察优秀的数据新闻,学习如何用图表传递信息。
以上就是Python可视化库Matplotlib与Seaborn的使用方法的详细内容,更多关于Python可视化库Matplotlib与Seaborn的资料请关注脚本之家其它相关文章!
