25 分面网格 FacetGrid
25 分面网格 FacetGrid
这类图是什么
底层分面容器,先建网格再 map 任意绘图函数。
看什么:seaborn 没有现成封装时,用它手动挂图实现分面。
5 个案例
25-1 通用分面:按季节切子图并挂直方图
FacetGrid 是"先建网格再 map 绘图函数"的底层容器,想画的分面图 seaborn 没有现成封装时,用它手动挂即可。

25-2 按区域分面并叠加密度曲线

25-3 按馈线分面 + hue 双重分组

25-4 按方案分面的回归散点

25-5 按月份分面的温升点线:共享坐标便于比较

代码
5 个函数取自 code/第五批_组合网格261107.py。关键约束:不调用 sns.set_theme(),否则 font.family 被改成 Arial,中文会变方框;版式由 code/公共配置261107.py 里的 setup_cn_style() 与 save() / save_grid() 统一接管。
# 摘自 code/第五批_组合网格261107.py
def fg_01():
"""通用分面:按季节切子图并挂直方图。
FacetGrid 是"先建网格再 map 绘图函数"的底层容器,
想画的分面图 seaborn 没有现成封装时,用它手动挂即可。
"""
fig, ax = new_fig(left=0.19)
fig.delaxes(ax)
rng = np.random.default_rng(2501)
rows = []
for s, mu in [("春季", 0.72), ("夏季", 0.84), ("秋季", 0.77), ("冬季", 0.74)]:
rows.append(pd.DataFrame({"负荷率": rng.normal(mu, 0.05, 180), "季节": s}))
df = pd.concat(rows, ignore_index=True)
g = sns.FacetGrid(df, col="季节", col_wrap=2, height=1.95, aspect=1.05,
sharex=True, sharey=True)
g.map_dataframe(sns.histplot, x="负荷率", color=C5, edgecolor="0.4",
linewidth=0.3)
g.set_axis_labels("日负荷率", "频次")
g.set_titles("{col_name}")
save_grid(g, "25_分面网格", "25_分面网格_按季节直方图",
left=0.155, bottom=0.14, right=0.97, top=0.90, w_mm=104, h_mm=86)
def fg_02():
"""按区域分面并叠加密度曲线。"""
fig, ax = new_fig(left=0.19)
fig.delaxes(ax)
rng = np.random.default_rng(2502)
rows = []
for a, mu, sd in [("城区", 0.6, 1.8), ("农村", 2.8, 3.4)]:
rows.append(pd.DataFrame({"偏差": rng.normal(mu, sd, 400), "区域": a}))
df = pd.concat(rows, ignore_index=True)
g = sns.FacetGrid(df, col="区域", height=2.6, aspect=1.5)
g.map_dataframe(sns.kdeplot, x="偏差", fill=True, color=C1, alpha=0.4)
g.set_axis_labels("电压偏差 / %", "概率密度")
g.set_titles("{col_name}")
save_grid(g, "25_分面网格", "25_分面网格_按区域密度",
left=0.165, bottom=0.18, right=0.97, top=0.86)
def fg_03():
"""按馈线分面 + hue 双重分组。"""
fig, ax = new_fig(left=0.19)
fig.delaxes(ax)
rng = np.random.default_rng(2503)
rows = []
for fd in ["L1", "L2"]:
for seg, mu in [("峰段", 650), ("谷段", 380)]:
rows.append(pd.DataFrame({"负荷": rng.normal(mu, 60, 150),
"时段": seg, "馈线": fd}))
df = pd.concat(rows, ignore_index=True)
g = sns.FacetGrid(df, col="馈线", hue="时段", palette=[C5, C1],
height=2.6, aspect=1.5)
g.map_dataframe(sns.histplot, x="负荷", bins=18, element="step",
fill=False, lw=1.0)
g.set_axis_labels("有功负荷 " + IT["P"] + " / kW", "频次")
g.set_titles("{col_name}")
g.add_legend(title="时段", framealpha=0.6)
save_grid(g, "25_分面网格", "25_分面网格_按馈线双重分组",
left=0.165, bottom=0.18, right=0.94, top=0.86)
def fg_04():
"""按方案分面的回归散点。"""
fig, ax = new_fig(left=0.19)
fig.delaxes(ax)
rng = np.random.default_rng(2504)
rows = []
for plan, mu, sd in [("原状", 4.62, 0.28), ("方案二", 3.24, 0.20)]:
b = rng.uniform(0.3, 1.1, 200)
rows.append(pd.DataFrame({"负载率": b, "线损率": mu * b ** 1.6
+ rng.normal(0, 0.18, 200), "方案": plan}))
df = pd.concat(rows, ignore_index=True)
g = sns.FacetGrid(df, col="方案", height=2.6, aspect=1.5)
g.map_dataframe(sns.regplot, x="负载率", y="线损率", color=C3,
scatter_kws={"s": 9, "edgecolor": "white", "linewidths": 0.2},
line_kws={"lw": 1.0})
g.set_axis_labels("负载率 " + IT["beta"], "年线损率 / %")
g.set_titles("{col_name}")
save_grid(g, "25_分面网格", "25_分面网格_按方案回归",
left=0.165, bottom=0.18, right=0.97, top=0.86)
def fg_05():
"""按月份分面的温升点线:共享坐标便于比较。"""
fig, ax = new_fig(left=0.19)
fig.delaxes(ax)
rng = np.random.default_rng(2505)
rows = []
for m, off in [("1 月", 0.0), ("7 月", 4.0)]:
for L in [0.6, 0.8, 1.0, 1.2]:
rows.append(pd.DataFrame({"温升": rng.normal(28 + 26 * L ** 2 + off, 2.6, 70),
"负载率": f"{L:.1f}", "月份": m}))
df = pd.concat(rows, ignore_index=True)
g = sns.FacetGrid(df, col="月份", height=2.6, aspect=1.5)
g.map_dataframe(sns.pointplot, x="负载率", y="温升", color=C1, markers="o",
ms=4, lw=1.0, capsize=0.10, errorbar=("ci", 95))
g.set_axis_labels("负载率 " + IT["beta"], "顶层油温升 " + IT["T"] + " / K")
g.set_titles("{col_name}")
save_grid(g, "25_分面网格", "25_分面网格_按月份点线",
left=0.165, bottom=0.18, right=0.97, top=0.86)
说明
- axes 级图 1181×944 px;figure 级多轴图按内容取 1100~1470 px 宽。
- 图内不放标题,图题由本文件的标题承担。
- 数据为 10 kV 配网、380 V 低压、50 Hz 量级的仿真算例,随机种子固定。

浙公网安备 33010602011771号