Seaborn是基于Matplotlib的高级数据可视化库,它提供了更简洁的API和更美观的默认样式,让你能够用更少的代码创建出更专业的统计图表。
与Matplotlib相比,Seaborn的优势在于:
本文将带你掌握Seaborn的核心技能。
Seaborn是基于Matplotlib的高级数据可视化库,专注于统计数据可视化。
# 使用pip安装
pip install seaborn matplotlib numpy pandas
# 或使用conda安装
conda install seaborn matplotlib numpy pandas
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
print("Seaborn版本:", sns.__version__)
print("环境搭建成功!")
# 设置中文字体
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 设置Seaborn风格
sns.set_style("whitegrid") # 可选: darkgrid, white, dark, ticks
sns.set_palette("viridis") # 可选: deep, muted, bright, pastel, dark, colorblind
箱线图适合展示数据的分布和异常值。
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 设置中文字体
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
sns.set_style("whitegrid")
# 加载示例数据
iris = sns.load_dataset('iris')
# 绘制箱线图
plt.figure(figsize=(12, 6))
sns.boxplot(x='species', y='sepal_length', data=iris,
palette='Set2', linewidth=2)
plt.title('不同品种鸢尾花的萼片长度分布', fontsize=14)
plt.xlabel('品种', fontsize=12)
plt.ylabel('萼片长度 (cm)', fontsize=12)
plt.show()
小提琴图结合了箱线图和密度图的特点。
plt.figure(figsize=(12, 6))
sns.violinplot(x='species', y='sepal_length', data=iris,
palette='Set2', inner='quartile') # inner可选: box, quartile, point, stick
plt.title('不同品种鸢尾花的萼片长度分布(小提琴图)', fontsize=14)
plt.xlabel('品种', fontsize=12)
plt.ylabel('萼片长度 (cm)', fontsize=12)
plt.show()
条形图显示分类变量的中心趋势估计。
tips = sns.load_dataset('tips')
plt.figure(figsize=(10, 6))
sns.barplot(x='day', y='total_bill', data=tips,
palette='viridis', ci=95) # ci表示置信区间
plt.title('每天的平均账单金额', fontsize=14)
plt.xlabel('星期', fontsize=12)
plt.ylabel('平均账单金额 ($)', fontsize=12)
plt.show()
计数图显示每个类别中的观测数量。
plt.figure(figsize=(10, 6))
sns.countplot(x='day', data=tips, palette='viridis', hue='time')
plt.title('每天的用餐人数', fontsize=14)
plt.xlabel('星期', fontsize=12)
plt.ylabel('人数', fontsize=12)
plt.legend(title='用餐时间')
plt.show()
点图用点和误差线显示中心趋势和置信区间。
plt.figure(figsize=(10, 6))
sns.pointplot(x='day', y='total_bill', data=tips,
hue='sex', palette='Set2', capsize=0.1)
plt.title('不同性别每天的平均账单', fontsize=14)
plt.xlabel('星期', fontsize=12)
plt.ylabel('平均账单 ($)', fontsize=12)
plt.legend(title='性别')
plt.show()
散点图展示两个变量之间的关系。
plt.figure(figsize=(10, 6))
sns.scatterplot(x='total_bill', y='tip', data=tips,
hue='sex', size='size', sizes=(50, 200),
palette='Set2', alpha=0.7)
plt.title('账单金额与小费的关系', fontsize=14)
plt.xlabel('账单金额 ($)', fontsize=12)
plt.ylabel('小费 ($)', fontsize=12)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
线图适合展示连续变量之间的关系。
# 创建时间序列数据
np.random.seed(42)
time = np.arange(100)
value1 = np.cumsum(np.random.randn(100))
value2 = np.cumsum(np.random.randn(100))
df_line = pd.DataFrame({'时间': time, '序列A': value1, '序列B': value2})
plt.figure(figsize=(12, 6))
sns.lineplot(x='时间', y='value', hue='variable',
data=pd.melt(df_line, ['时间']),
palette='Set2', linewidth=2)
plt.title('时间序列对比', fontsize=14)
plt.xlabel('时间', fontsize=12)
plt.ylabel('值', fontsize=12)
plt.show()
联合分布图同时展示两个变量的关系和各自的分布。
g = sns.jointplot(x='total_bill', y='tip', data=tips,
kind='reg', height=8, color='#4ECDC4')
g.fig.suptitle('账单金额与小费的关系', fontsize=14, y=1.02)
g.set_axis_labels('账单金额 ($)', '小费 ($)', fontsize=12)
plt.show()
配对图展示数据集中所有变量两两之间的关系。
g = sns.pairplot(iris, hue='species', palette='Set2',
diag_kind='kde', height=2.5)
g.fig.suptitle('鸢尾花数据配对图', fontsize=16, y=1.02)
plt.show()
直方图展示单变量的分布。
plt.figure(figsize=(10, 6))
sns.histplot(data=tips, x='total_bill', bins=20,
kde=True, color='#45B7D1', edgecolor='black')
plt.title('账单金额分布', fontsize=14)
plt.xlabel('账单金额 ($)', fontsize=12)
plt.ylabel('频率', fontsize=12)
plt.show()
KDE图展示连续变量的概率密度。
plt.figure(figsize=(10, 6))
sns.kdeplot(data=tips, x='total_bill', hue='time',
fill=True, palette='Set2', alpha=0.5, linewidth=2)
plt.title('不同用餐时间的账单金额分布', fontsize=14)
plt.xlabel('账单金额 ($)', fontsize=12)
plt.ylabel('密度', fontsize=12)
plt.show()
Rugplot在坐标轴上显示每个数据点。
plt.figure(figsize=(10, 6))
sns.kdeplot(data=tips, x='total_bill', color='#4ECDC4', fill=True)
sns.rugplot(data=tips, x='total_bill', color='#FF6B6B', height=0.05)
plt.title('账单金额分布(带rugplot)', fontsize=14)
plt.xlabel('账单金额 ($)', fontsize=12)
plt.ylabel('密度', fontsize=12)
plt.show()
ECDF(经验累积分布函数)图展示数据的累积分布。
plt.figure(figsize=(10, 6))
sns.ecdfplot(data=tips, x='total_bill', hue='sex',
palette='Set2', linewidth=2)
plt.title('账单金额的累积分布', fontsize=14)
plt.xlabel('账单金额 ($)', fontsize=12)
plt.ylabel('ECDF', fontsize=12)
plt.show()
热力图非常适合展示相关性矩阵。
# 计算相关性矩阵
corr = iris.corr(numeric_only=True)
plt.figure(figsize=(10, 8))
sns.heatmap(corr, annot=True, cmap='coolwarm',
center=0, square=True, linewidths=1,
cbar_kws={"shrink": 0.8}, fmt='.2f')
plt.title('鸢尾花数据相关性热力图', fontsize=14)
plt.xticks(rotation=45, ha='right')
plt.yticks(rotation=0)
plt.tight_layout()
plt.show()
聚类热力图同时对行和列进行层次聚类。
g = sns.clustermap(iris.drop('species', axis=1),
cmap='coolwarm', standard_scale=1,
figsize=(10, 8))
g.fig.suptitle('鸢尾花数据聚类热力图', fontsize=14, y=1.02)
plt.show()
# 查看可用样式
print(sns.axes_style())
# 试用不同样式
styles = ['darkgrid', 'whitegrid', 'dark', 'white', 'ticks']
fig, axes = plt.subplots(1, 5, figsize=(20, 4))
for i, style in enumerate(styles):
sns.set_style(style)
sns.histplot(data=tips, x='total_bill', ax=axes[i], color='#4ECDC4')
axes[i].set_title(style)
axes[i].set_xlabel('')
axes[i].set_ylabel('')
plt.tight_layout()
plt.show()
# 恢复默认样式
sns.set_style("whitegrid")
# 查看可用调色板
print(sns.color_palette())
# 试用不同调色板
palettes = ['deep', 'muted', 'bright', 'pastel', 'dark', 'colorblind',
'Set2', 'viridis', 'coolwarm']
fig, axes = plt.subplots(3, 3, figsize=(15, 12))
axes = axes.flatten()
for i, palette in enumerate(palettes):
sns.set_palette(palette)
sns.barplot(x='day', y='total_bill', data=tips, ax=axes[i])
axes[i].set_title(palette)
axes[i].set_xlabel('')
axes[i].set_ylabel('')
plt.tight_layout()
plt.show()
# 恢复默认调色板
sns.set_palette("viridis")
# 试用不同上下文
contexts = ['paper', 'notebook', 'talk', 'poster']
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
axes = axes.flatten()
for i, context in enumerate(contexts):
sns.set_context(context, font_scale=1.2)
sns.histplot(data=tips, x='total_bill', ax=axes[i], color='#4ECDC4')
axes[i].set_title(context)
plt.tight_layout()
plt.show()
# 恢复默认上下文
sns.set_context("notebook", font_scale=1)
我们有一份销售数据,包含以下字段:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
# 设置中文字体和样式
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
sns.set_style("whitegrid")
sns.set_palette("viridis")
# 创建模拟数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', '2024-12-31', freq='D')
products = ['智能手机', '笔记本电脑', '平板电脑', '耳机', '充电器']
categories = ['电子产品', '电子产品', '电子产品', '配件', '配件']
data = {
'date': np.random.choice(dates, 1000),
'product': np.random.choice(products, 1000),
'category': np.random.choice(categories, 1000),
'quantity': np.random.randint(1, 10, 1000),
'price': np.random.choice([2999, 5999, 1999, 299, 99], 1000)
}
df = pd.DataFrame(data)
df['revenue'] = df['quantity'] * df['price']
df['month'] = df['date'].dt.month
# 1. 产品类别销售分布
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))
# 箱线图
sns.boxplot(x='category', y='revenue', data=df, ax=ax1, palette='Set2')
ax1.set_title('不同类别的销售额分布', fontsize=14)
ax1.set_xlabel('类别', fontsize=12)
ax1.set_ylabel('销售额', fontsize=12)
# 小提琴图
sns.violinplot(x='category', y='revenue', data=df, ax=ax2, palette='Set2')
ax2.set_title('不同类别的销售额分布(小提琴图)', fontsize=14)
ax2.set_xlabel('类别', fontsize=12)
ax2.set_ylabel('销售额', fontsize=12)
plt.tight_layout()
plt.show()
# 2. 价格与销售额的关系
plt.figure(figsize=(12, 6))
sns.scatterplot(x='price', y='revenue', data=df,
hue='category', size='quantity', sizes=(50, 300),
palette='Set2', alpha=0.6)
plt.title('价格与销售额的关系', fontsize=14)
plt.xlabel('价格', fontsize=12)
plt.ylabel('销售额', fontsize=12)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
# 3. 月度销售情况
plt.figure(figsize=(12, 6))
sns.barplot(x='month', y='revenue', data=df,
palette='viridis', errorbar=('ci', 95))
months = ['1月', '2月', '3月', '4月', '5月', '6月',
'7月', '8月', '9月', '10月', '11月', '12月']
plt.title('月度平均销售额', fontsize=14)
plt.xlabel('月份', fontsize=12)
plt.ylabel('平均销售额', fontsize=12)
plt.xticks(range(12), months)
plt.show()
# 4. 相关性热力图
corr = df[['quantity', 'price', 'revenue']].corr()
plt.figure(figsize=(8, 6))
sns.heatmap(corr, annot=True, cmap='coolwarm',
center=0, square=True, linewidths=1, fmt='.2f')
plt.title('销售数据相关性热力图', fontsize=14)
plt.tight_layout()
plt.show()
Seaborn让统计数据可视化变得简单而优雅。通过本文的学习,你已经掌握了:
Seaborn和Matplotlib配合使用,可以满足绝大多数数据可视化需求。记住,好的可视化是技术和艺术的结合,多实践、多尝试,你会越来越熟练!
小贴士:Seaborn是Matplotlib的高级封装,掌握Matplotlib基础能让你更好地理解和使用Seaborn。遇到复杂需求时,可以直接使用Matplotlib进行定制。