如何在Altair中创建精准停靠于插值曲线的mark_rule
解决Altair中精准定位垂直标线到CDF曲线指定X位置的问题
问题原因
你当前的方法依赖于transform_quantile生成的离散数据点,只能找到最接近目标X的现有数据点,无法精准定位到任意指定X值;同时强制指定X后,没有对应的插值Y值,导致标线高度不匹配曲线。
简洁解决方案
方法1:直接计算目标X对应的经验CDF值
因为CDF的本质是样本中小于等于目标X的观测值占比,可以直接计算该值,然后用XDatum和Y2Datum创建精准标线:
import numpy as np import altair as alt import scipy import polars as pl np.random.seed(1) _data = pl.DataFrame({"x": scipy.stats.norm().rvs(200)}) _cdf = ( alt.Chart(_data).mark_area(opacity=0.7) .transform_quantile(quantile="x", as_=["prob", "value"]) .encode( alt.X("value:Q"), alt.Y("prob:Q"), ) ) _rule_x = 0 # 计算目标X对应的经验CDF值 total = len(_data["x"]) rule_y = (_data["x"] <= _rule_x).sum() / total # 创建垂直标线:从Y=0到计算出的CDF高度,X精准定位到目标值 _rule = alt.Chart().mark_rule(color='red', strokeWidth=2).encode( alt.XDatum(_rule_x), alt.YDatum(0), alt.Y2Datum(rule_y) ) _cdf + _rule
方法2:用Altair回归拟合CDF曲线并预测目标点
如果需要依赖Altair的变换逻辑(避免手动计算),可以用transform_regression拟合CDF曲线,然后预测目标X对应的Y值:
import numpy as np import altair as alt import scipy import polars as pl np.random.seed(1) _data = pl.DataFrame({"x": scipy.stats.norm().rvs(200)}) # 生成CDF离散数据 cdf_source = ( alt.Chart(_data) .transform_quantile(quantile="x", as_=["prob", "value"]) .transform_calculate(x="datum.value", y="datum.prob") ).to_dict()['data'] _cdf = ( alt.Chart(_data).mark_area(opacity=0.7) .transform_quantile(quantile="x", as_=["prob", "value"]) .encode( alt.X("value:Q"), alt.Y("prob:Q"), ) ) _rule_x = 0 # 拟合CDF曲线并预测目标X的Y值 _rule = ( alt.Chart(cdf_source) .transform_regression( "x", "y", method="poly", order=5, as_=["x_pred", "y_pred"] ) .transform_filter(f"datum.x_pred == {_rule_x}") .mark_rule(color='red', strokeWidth=2) .encode( alt.X("x_pred:Q"), alt.Y("y_pred:Q"), alt.Y2Datum(0) ) ) _cdf + _rule
关键说明
- 方法1更高效精准,直接利用经验CDF的定义计算,无需依赖Altair的离散数据点;
- 方法2适合需要动态调整拟合曲线的场景,通过多项式回归拟合CDF的连续曲线,再预测目标点值;
- 两种方法都能实现X精准定位到任意指定值,且标线高度完全匹配对应位置的CDF曲线高度。
内容的提问来源于stack exchange,提问作者Juan Martinez
相关产品推荐
相关产品推荐

