如何用Seaborn更简洁绘制单变量样本的超越概率(1-CDF)图?
Got it, let's break this down clearly. 超越概率本质就是1减去累积分布函数(CDF)(也就是P(X > x)),刚好可以基于你已经熟悉的Seaborn工具实现,结合FacetGrid做分面也非常顺畅。
先讲最简洁优雅的现代实现(推荐)
Seaborn 0.11+推出的ecdfplot直接支持绘制互补ECDF(也就是超越概率),不用手动转换,一步到位。先看单组数据的情况:
import seaborn as sns import matplotlib.pyplot as plt import pandas as pd import numpy as np # 构造示例单列DataFrame(如果你的数据已经是这样,跳过这步) np.random.seed(42) df = pd.DataFrame({'latency': np.random.normal(60, 12, 1000)}) # 绘制超越概率图 plt.figure(figsize=(8, 5)) sns.ecdfplot(data=df, x='latency', complementary=True, linewidth=2) plt.ylabel('超越概率 P(X > x)') plt.xlabel('Latency') plt.title('Latency 超越概率曲线') plt.show()
这里的complementary=True就是告诉Seaborn直接绘制1 - CDF,完美契合超越概率的需求,比手动处理CDF要简洁太多。
结合FacetGrid实现分组分面的超越概率图
如果你的DataFrame有分组字段(比如不同实验场景、不同用户群体),用FacetGrid可以快速生成多子图的超越概率对比:
# 构造带分组的示例DataFrame np.random.seed(42) df = pd.DataFrame({ 'latency': np.concatenate([np.random.normal(50, 10, 500), np.random.normal(70, 15, 500)]), 'group': ['场景A']*500 + ['场景B']*500 }) # 用FacetGrid分面绘制 g = sns.FacetGrid(df, col='group', height=4, aspect=1.2) # 在每个子图上绘制互补ECDF(超越概率) g.map(sns.ecdfplot, 'latency', complementary=True, linewidth=2) # 统一设置轴标签和标题 g.set_axis_labels('Latency', '超越概率 P(X > x)') g.set_titles('{col_name}') plt.tight_layout() plt.show()
如果你一定要基于distplot实现(兼容旧版Seaborn)
如果你的Seaborn版本较低(<0.11),还在使用distplot,可以通过绘制CDF后反转y轴并转换含义来实现:
# 单组情况 plt.figure(figsize=(8, 5)) # 绘制归一化的累积直方图(即CDF) sns.distplot(df['latency'], kde=False, hist_kws={'cumulative': True, 'density': True}) ax = plt.gca() # 反转y轴,将CDF转换为超越概率(1 - CDF) ax.set_ylim(ax.get_ylim()[::-1]) ax.set_ylabel('超越概率 P(X > x)') ax.set_xlabel('Latency') plt.title('基于distplot的超越概率曲线') plt.show() # 结合FacetGrid的情况 def plot_exceedance(x, **kwargs): sns.distplot(x, kde=False, hist_kws={'cumulative': True, 'density': True}, **kwargs) ax = plt.gca() ax.set_ylim(ax.get_ylim()[::-1]) ax.set_ylabel('超越概率 P(X > x)') g = sns.FacetGrid(df, col='group', height=4, aspect=1.2) g.map(plot_exceedance, 'latency') g.set_axis_labels('Latency', '超越概率 P(X > x)') g.set_titles('{col_name}') plt.tight_layout() plt.show()
小提示
- 反转y轴是因为超越概率随x增大而递减,这样的视觉呈现更符合我们对“越大的x,超越它的概率越低”的直观认知。
- 新版Seaborn更推荐使用
ecdfplot/histplot替代distplot,前者的API更清晰,功能也更强大。
内容的提问来源于stack exchange,提问作者Bhushan




