You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HvPlot+Bokeh对数尺度下小提琴图显示异常的技术求助

解决HvPlot+Bokeh小提琴图对数尺度下箱型异常的问题

问题根源

当设置logy=True时,HvPlot默认是先基于原始数据计算箱型统计量(分位数、极值等),再将这些数值映射到对数坐标轴,而非在对数空间内计算统计量。这就导致分位数在对数轴上的位置与实际分布脱节,出现Q2(中位数)超出小提琴分布范围的异常。

解决方案

方法1:自定义箱型统计量(无需修改原始数据)

手动在对数空间计算分位数、极值等统计量,转换回原始尺度后,通过box_plot_kwargs传入小提琴图,让箱型与对数空间的分布匹配。

代码示例:

import hvplot.pandas
import pandas as pd
import numpy as np
hvplot.extension('bokeh')

temp = [3.021e+00, 1.726e+00, 2.092e+00, 1.721e+00,    np.nan, 3.182e+00, 8.335e+00,
        9.851e+00, 9.743e+00, 3.153e+01,    np.nan, 2.458e+01, 1.138e+01, 9.886e+01,
        1.638e+01, 1.084e+00, 1.573e+00, 2.486e-01, 4.257e-01, 2.447e-01, 3.540e-01,
        3.644e-01, 3.296e-01, 3.450e-01, 2.739e-01, 3.404e-01, 4.427e-01, 8.187e-01,
        4.360e-01, 3.556e-01, 3.107e+00, 9.722e-01, 1.572e+00, 7.006e-01, 2.344e-01,
        9.597e-01, 1.372e-01, 2.530e-01, 1.100e+00, 5.791e+00, 1.093e+01, 4.249e+00,
        4.841e+00, 5.234e+00, 1.355e+01, 1.423e+01, 2.478e+01,    np.nan, 4.721e+01,
           np.nan, 9.234e+01,    np.nan, 1.045e+02,    np.nan, 8.989e+01,    np.nan,
        9.330e+01,    np.nan, 1.151e+02,    np.nan, 2.193e+02,    np.nan, 1.705e+02,
           np.nan, 3.835e+02,    np.nan, 1.689e+03,    np.nan, 1.879e+03,    np.nan,
        1.898e+03,    np.nan, 2.374e+03,    np.nan, 3.079e+03, 3.611e+03, 3.926e+03]

test = pd.Series(temp)

# 1. 过滤NaN,计算对数空间的统计量
valid_data = test.dropna()
log_data = np.log10(valid_data)

# 计算对数空间的分位数和极值
q1_log = np.percentile(log_data, 25)
q2_log = np.percentile(log_data, 50)
q3_log = np.percentile(log_data, 75)
iqr_log = q3_log - q1_log
lower_whisker_log = max(log_data.min(), q1_log - 1.5*iqr_log)
upper_whisker_log = min(log_data.max(), q3_log + 1.5*iqr_log)

# 转换回原始尺度
custom_stats = {
    'q1': 10**q1_log,
    'median': 10**q2_log,
    'q3': 10**q3_log,
    'lower': 10**lower_whisker_log,
    'upper': 10**upper_whisker_log
}

# 2. 绘制小提琴图,传入自定义统计量
plt = test.hvplot.violin(
    logy=True,
    box_plot_kwargs={'stats': custom_stats}
)
hvplot.show(plt)

方法2:直接使用Holoviews底层控制

HvPlot是Holoviews的封装,直接使用Holoviews的Violin元素可以更灵活地控制分布计算逻辑,在对数空间生成小提琴分布,再设置y轴为对数尺度。

代码示例:

import hvplot.pandas
import pandas as pd
import numpy as np
import holoviews as hv
hv.extension('bokeh')

temp = [3.021e+00, 1.726e+00, 2.092e+00, 1.721e+00,    np.nan, 3.182e+00, 8.335e+00,
        9.851e+00, 9.743e+00, 3.153e+01,    np.nan, 2.458e+01, 1.138e+01, 9.886e+01,
        1.638e+01, 1.084e+00, 1.573e+00, 2.486e-01, 4.257e-01, 2.447e-01, 3.540e-01,
        3.644e-01, 3.296e-01, 3.450e-01, 2.739e-01, 3.404e-01, 4.427e-01, 8.187e-01,
        4.360e-01, 3.556e-01, 3.107e+00, 9.722e-01, 1.572e+00, 7.006e-01, 2.344e-01,
        9.597e-01, 1.372e-01, 2.530e-01, 1.100e+00, 5.791e+00, 1.093e+01, 4.249e+00,
        4.841e+00, 5.234e+00, 1.355e+01, 1.423e+01, 2.478e+01,    np.nan, 4.721e+01,
           np.nan, 9.234e+01,    np.nan, 1.045e+02,    np.nan, 8.989e+01,    np.nan,
        9.330e+01,    np.nan, 1.151e+02,    np.nan, 2.193e+02,    np.nan, 1.705e+02,
           np.nan, 3.835e+02,    np.nan, 1.689e+03,    np.nan, 1.879e+03,    np.nan,
        1.898e+03,    np.nan, 2.374e+03,    np.nan, 3.079e+03, 3.611e+03, 3.926e+03]

test = pd.Series(temp).dropna()
log_data = np.log10(test)

# 在对数空间生成小提琴图,再将y轴转换为原始尺度的对数轴
violin = hv.Violin(log_data, vdims='value').opts(
    yformatter='%e',  # 用科学计数法显示原始尺度数值
    yaxis_type='log',
    yticks=[10**i for i in range(-1, 4)]  # 自定义刻度对应原始尺度
)
hvplot.show(violin)

说明

两种方法都无需修改原始数据集:

  • 方法1保留了HvPlot的便捷性,仅通过自定义统计量修正箱型位置;
  • 方法2利用Holoviews的底层能力,直接在对数空间生成分布,更贴合对数尺度的展示逻辑。

内容的提问来源于stack exchange,提问作者Murnawful

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:44:59