多图网格
核心函数
sns.FaceGrid():分面网格,按字段生成子图矩阵
sns.PairGrid():成对网格,展示变量间的两两关系
sns.jointplot():联合图,展示双变量分布+单变量分布
关键参数
data:输入DataFrame
row/col:按字段分行/列生成子图
hue:分组字段
kind:子图类型('scatter'、'reg'、'kde'等)
实例
分面网格
python
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd
np.random.seed(123)
#POI日均曝光量
exposure = np.random.uniform(200, 800, size=800)
#POI线上推广投入
promotion = np.random.uniform(500, 3000, size=800)
#POI日均点击量
click = 0.7 * exposure + np.random.normal(0, 60, size=800)
#POI日均营业额
revenue = 120 * click + 0.5 * promotion + np.random.normal(0, 1000, size=800)
#
data = pd.DataFrame({
#城市
'城市': np.random.choice(['北京', '上海', '广州', '深圳'], size=800),
#商圈类型
'商圈类型': np.random.choice(['核心商圈', '区域商圈', '社区商圈'], size=800),
# 时段
'时段': np.random.choice(['工作日', '周末'], size=800, p=[0.6, 0.4]),
# POI日均曝光量
'poi日均曝光量': exposure,
# POI线上推广投入
'poi推广投入': promotion,
#POI日均点击量
'poi日均点击量': click,
# POI日均营业额
'poi日均营业额': revenue
})
numeric_cols = ['poi日均点击量', 'poi日均营业额']
data[numeric_cols] = data[numeric_cols].clip(lower=0)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
sns.set_theme(style='whitegrid',font='SimHei',font_scale=1.0)
#单分面,按城市拆分,填充散点图,展示曝光量VS点击量
#创建分面网格
g1=sns.FacetGrid(
data=data,
col='城市',#按城市分列,每个城市一子图
col_wrap=2,#每行显示2个子图
hue='商圈类型',
palette='coolwarm',
height=4,#单个子图高度
aspect=1.1#单个子图宽高比
)
#为每个子图填充散点图
g1.map(sns.scatterplot,
'poi日均曝光量', 'poi日均点击量',
alpha=0.7,
s=30#散点大小
)
g1.add_legend(title='商圈类型',fontsize=5,loc='upper left')#将图例放在左上角
g1.set_titles('{col_name}')
g1.set_xlabels('POI日均曝光量')
g1.set_ylabels('POI日均点击量')
g1.figure.suptitle('各城市POI曝光量vs点击量', y=1.0)
#双分面,按时段、城市拆分,填充核密度图
#创建双分面网格
g2=sns.FacetGrid(
data=data,
row='时段',
col='城市',
hue='商圈类型',
height=4,
aspect=1.1
)
#为每个子图填充核密度图
g2.map(
sns.kdeplot,
'poi日均营业额',
fill=True,
alpha=0.4
)
g2.add_legend(title='商圈类型',fontsize=5,loc='upper left')
g2.set_titles('{row_name}-{col_name}')
g2.set_xlabels('POI日均营业额')
g2.set_ylabels('概率密度')
g2.figure.suptitle('各时段&城市POI营业额分布', y=1.0)
plt.tight_layout()
plt.show()


g1.map(plot_func, x, y, ..., **kwargs)
plot_func:必选参数,指定要填充到子图中的图表类型,这个参数只写函数名,不加括号
x, y:必选参数,指定传给plot_func的数据列名
成对网格
python
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd
np.random.seed(123)
#POI日均曝光量
exposure = np.random.uniform(200, 800, size=800)
#POI线上推广投入
promotion = np.random.uniform(500, 3000, size=800)
#POI日均点击量
click = 0.7 * exposure + np.random.normal(0, 60, size=800)
#POI日均营业额
revenue = 120 * click + 0.5 * promotion + np.random.normal(0, 1000, size=800)
#
data = pd.DataFrame({
#城市
'城市': np.random.choice(['北京', '上海', '广州', '深圳'], size=800),
#商圈类型
'商圈类型': np.random.choice(['核心商圈', '区域商圈', '社区商圈'], size=800),
# 时段
'时段': np.random.choice(['工作日', '周末'], size=800, p=[0.6, 0.4]),
# POI日均曝光量
'poi日均曝光量': exposure,
# POI线上推广投入
'poi推广投入': promotion,
#POI日均点击量
'poi日均点击量': click,
# POI日均营业额
'poi日均营业额': revenue
})
numeric_cols = ['poi日均点击量', 'poi日均营业额']
data[numeric_cols] = data[numeric_cols].clip(lower=0)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
sns.set_theme(style='whitegrid',font='SimHei',font_scale=1.0)
#自定义数值字段,hue分组
#创建成对网格,指定要分析的字段
vars = ['poi日均曝光量', 'poi推广投入', 'poi日均点击量', 'poi日均营业额']
g1=sns.PairGrid(
data=data,
vars=vars,#指定要展示两两关系的数值字段
hue='商圈类型',
palette='coolwarm',
height=2.8,#单个子图高度
aspect=1.0,#单个子图宽高比
diag_sharey=False#对角线子图不共享Y轴,避免分布图形变形
)
#为每个子图填充图
g1.map_diag(sns.kdeplot,#对角线:单变量核密度图
fill=True,
alpha=0.7
)
g1.map_offdiag(sns.scatterplot,alpha=0.6,s=20)#非对角线:双变量散点图
g1.add_legend(title='商圈类型',fontsize=6,loc='upper right')#将图例放在左上角
g1.figure.suptitle('POI运营指标两两关系', y=1.0)
plt.tight_layout()
plt.show()
#非对角线改为回归图
g2=sns.PairGrid(
data=data,
vars=['poi日均曝光量', 'poi日均点击量', 'poi日均营业额'],
hue='商圈类型',
height=2.8,
aspect=1.0,
diag_sharey=False
)
g2.map_diag(sns.histplot, kde=True, alpha=0.6) # 对角线:直方图+核密度曲线
g2.map_offdiag(sns.regplot, scatter_kws={'alpha': 0.4, 's': 15}, line_kws={'linewidth': 1}) # 非对角线:回归图
g2.add_legend(title='商圈类型',fontsize=6,loc='upper right')
g2.figure.suptitle('POI核心指标两两回归关系', y=1.0)
plt.tight_layout()
plt.show()


样式与调色板
样式管理
sns.set_style():预设风格('white' 'dark' 'whitegrid' 'darkgrid' 'ticks')
sns.despine():移除图表的上/右边框
sns.set_context():设置绘图上下文('paper' 'notebook' 'talk' 'poster'),核心作用就是规范预设的尺寸,实现「一键缩放」整个图表的元素大小,而不改变图表的样式、配色和逻辑结构。

调色板
sns.color_palette():创建获取调色板
分类调色板:'husl' 'tab10' 'Set2'
连续调色板:'viridis' 'coolwarm' 'rocket'
发散调色板:'vlag' 'icefire'
在seaborn绘图(上)一章中第一个代码的基础上,进行美化
python
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd
data=pd.DataFrame(
{
'城市':['北京','上海','广州','深圳','杭州']*4,
'季度':['Q1','Q2','Q3','Q4']*5,
'poi新增量':np.random.randint(500,2000,20)
}
)
#设置自定义风格
sns.set_style('darkgrid',{'axes.facecolor':'#f5f5f5'})
sns.set_context('notebook',font_scale=1.0)
palette=sns.set_palette(['#2ecc71','#3498db','#f1c40f','#e74c3c'])
#创建画布
fig,ax=plt.subplots(figsize=(10,6))
#绘制基础柱状图
sns.barplot(
data=data,
x='城市',
y='poi新增量',
hue='季度', #按季度分组
palette=palette,
alpha=0.6,
ax=ax#指定将柱状图绘制在前面创建的坐标系ax上,如不指定,会自动创建一个新的坐标系
)
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
plt.rcParams['axes.unicode_minus']=False
#添加元素
ax.set_title('各城市季度poi新增量对比')
ax.set_xlabel('城市')
ax.set_ylabel('poi新增量')
#美化
sns.despine(top=True,right=True)#移除上/右边框
plt.tight_layout()#自动调整图表中各元素的位置和间距
plt.show()

运行中遇到的问题:即使设置了中文配置问题的解决,但仍显示为方块。
原因:将plt.rcParams['font.sans-serif']=['SimHei']写在了sns.set_style() 和 sns.set_context()前面;这两个函数会重新初始化部分 Matplotlib 的绘图参数,其中就包含字体相关配置,相当于把之前设置的「黑体」给覆盖掉了,恢复了 Seaborn 的默认字体。
解决:调换代码的先后顺序,Seaborn 的配置函数(set_style()/set_context())要放在 Matplotlib 的中文配置之前。
Kepler.gl地理数据可视化
Kepler.gl是Uber开源的高性能地理数据可视化工具,支持大规模点、线、面数据的交互可视化,无需前端开发即可制作专业地图
关键操作
KeplerGl():创建地图实例
python
KeplerGl(
data=None, # 直接传入数据集,支持DataFrame/GeoJSON格式
config=None, # 地图配置(样式、图层、交互规则等,默认自动生成)
height=600, # 地图高度(像素),默认600
width=None, # 地图宽度(像素),默认None
read_only=False #是否只读(禁止修改地图配置),默认False
)
add_data():添加数据集
python
map_instance.add_data(
data, # 必选,地理数据集(pandas.DataFrame 或 GeoJSON)
name=None, # 数据集名称
overwrite=False # 是否覆盖已存在的同名数据集,默认False
)
save_to_html():保存为可交互的HTML文件
python
map_instance.save_to_html(
file_name='keplergl_map.html', #保存的HTML文件名(含路径),默认#keplergl_map.html
config=None, #额外传入的地图配置(覆盖地图实例中的配置)
read_only=False #是否设置为只读模式,默认False
)
完整代码
python
from keplergl import KeplerGl
import pandas as pd
#实验数据(必须包含经纬度)
city_poi_data = pd.DataFrame({
'城市': ['北京', '上海', '广州', '深圳', '杭州', '成都', '重庆'],
'季度': ['Q3', 'Q3', 'Q3', 'Q3', 'Q3', 'Q3', 'Q3'],
'经度': [116.4074, 121.4737, 113.2644, 114.0579, 120.1590, 104.0657, 106.5049],
'纬度': [39.9042, 31.2304, 23.1291, 22.5431, 30.2795, 30.6594, 29.5630],
'POI新增量': [1800, 1950, 1700, 1650, 1500, 1400, 1350]
})
#创建地图实例
poi_map=KeplerGl(height=800,read_only=False)
#添加数据集
poi_map.add_data(data=city_poi_data,name='各城市第三季度poi新增量')
#保存为可分享的HTML文件
poi_map.save_to_html(file_name=r'C:\Users\Lenovo\Desktop\Python\visualize.html')
感觉渲染得好慢,不好用不好用。