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

C# Oxyplot水平箱线图转换及概率密度图绘制技术咨询

解决方案:Oxyplot水平箱线图与概率密度图实现

我来帮你解决这两个Oxyplot的问题,这俩场景我之前也折腾过,给你详细说下:

一、实现水平箱线图(解决数据无法读取的问题)

你之前直接交换Linear和Category轴的位置导致数据异常,是因为箱线图系列的方向和轴的映射关系没对应上——单纯换轴位置,但箱线图还是默认垂直方向渲染,数据绑定逻辑就乱了。正确的做法是直接修改箱线图系列的方向属性,再配合轴的配置:

具体步骤:

  1. 给BoxPlotSeries设置Orientation = BoxPlotOrientation.Horizontal,明确告诉系列要水平渲染
  2. 配置坐标轴:
    • 用CategoryAxis作为Y轴(比如放在左侧),用来显示你的类别标签
    • 用LinearAxis作为X轴(放在底部),用来展示数值范围
  3. 按顺序给箱线图添加数据(数据顺序要和CategoryAxis的标签顺序对应)

示例代码(C#):

// 初始化图表模型
var plotModel = new PlotModel { Title = "水平箱线图示例" };

// Y轴:类别轴(左侧)
var categoryAxis = new CategoryAxis { Position = AxisPosition.Left };
categoryAxis.Labels.Add("实验组A");
categoryAxis.Labels.Add("实验组B");
categoryAxis.Labels.Add("对照组");
plotModel.Axes.Add(categoryAxis);

// X轴:数值轴(底部)
var linearAxis = new LinearAxis { Position = AxisPosition.Bottom, Title = "测量值" };
plotModel.Axes.Add(linearAxis);

// 创建水平箱线图系列
var boxPlotSeries = new BoxPlotSeries { Orientation = BoxPlotOrientation.Horizontal };

// 添加箱线数据:每个Item对应[最小值, 下四分位, 中位数, 上四分位, 最大值]
boxPlotSeries.Items.Add(new BoxPlotItem(12, 18, 22, 26, 30));
boxPlotSeries.Items.Add(new BoxPlotItem(8, 15, 20, 24, 28));
boxPlotSeries.Items.Add(new BoxPlotItem(15, 21, 25, 29, 33));

plotModel.Series.Add(boxPlotSeries);

这样配置后,箱线图就会水平渲染,数据也能正确映射到对应的轴上。

二、绘制概率密度图

Oxyplot本身没有内置的概率密度图系列,但我们可以用LineSeries配合**核密度估计(KDE)**来实现——先对原始数据计算出概率密度的数值点,再用折线图把这些点连起来。

具体步骤:

  1. 对原始数据进行核密度估计,生成密度曲线的坐标点
  2. 用LineSeries绘制这些坐标点,就得到概率密度图

示例代码(C#):

// 你的原始样本数据
var rawData = new double[] { 1.1, 1.5, 1.7, 2.0, 2.2, 2.4, 2.6, 2.9, 3.1, 3.3 };

// 计算概率密度曲线的坐标点(带宽可根据数据调整)
var kdePoints = CalculateKernelDensity(rawData, bandwidth: 0.3);

// 初始化图表模型
var plotModel = new PlotModel { Title = "概率密度图示例" };

// 添加坐标轴
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "数值" });
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "概率密度" });

// 创建折线系列绘制密度曲线
var densitySeries = new LineSeries { Title = "核密度估计", StrokeThickness = 2 };
foreach (var point in kdePoints)
{
    densitySeries.Points.Add(new DataPoint(point.X, point.Y));
}

plotModel.Series.Add(densitySeries);

// 核密度估计的实现(高斯核)
List<DataPoint> CalculateKernelDensity(double[] data, double bandwidth)
{
    var minX = data.Min() - bandwidth * 3; // 扩展范围避免边缘截断
    var maxX = data.Max() + bandwidth * 3;
    var step = (maxX - minX) / 100; // 分成100个采样点,可调整精度
    var points = new List<DataPoint>();

    for (var x = minX; x <= maxX; x += step)
    {
        // 计算每个x点的密度值
        var density = data.Sum(d => GaussianKernel(x - d, bandwidth)) / (data.Length * bandwidth);
        points.Add(new DataPoint(x, density));
    }

    return points;
}

// 高斯核函数
double GaussianKernel(double x, double bandwidth)
{
    var normalization = 1.0 / Math.Sqrt(2 * Math.PI * Math.Pow(bandwidth, 2));
    return normalization * Math.Exp(-Math.Pow(x, 2) / (2 * Math.Pow(bandwidth, 2)));
}

如果需要更专业的统计计算,也可以用MathNet.Numerics这类第三方库来实现核密度估计,效率和精度会更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:15:39