使用 c# 复制 Excel 次幂趋势线值

Replicate Excel Power Trendline values with c#

我需要在代码中复制此 Excel 图

给定 [x, y] 值列表,如何获取新的值列表来绘制幂趋势线?

我发现有人提到这个 http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html 公式。但是不知道如何从中生成新的值列表。

遵循 link 中的公式:

function getFittedPoints(data) {
  var log = Math.log,
    pow = Math.pow,

    sums = [
        0, // sum of the logarithms of x ( sum(log(x)) )
        0, // sum of the logarithms of y ( sum(log(y)) )
        0, // sum of the logarithms of the products of x and y ( sum(log(x) * log(y)) )
        0 // sum of the powers of the logarithms of x ( sum((log(x))^2 )
    ],
    fittedPoints = [], // return fitted points
    a, // a coefficient
    b, // b coefficient

    dataLen = data.length,
    i,
    logX,
    logY;

  for (i = 0; i < dataLen; i++) {
    sums[0] += logX = log(data[i][0]);
    sums[1] += logY = log(data[i][1]);
    sums[2] += logX * logY;
    sums[3] += pow(logX, 2);
  }

  b = (i * sums[2] - sums[0] * sums[1]) / (i * sums[3] - pow(sums[0], 2));
  a = pow(Math.E, (sums[1] - b * sums[0]) / i);

  for (i = 0; i < dataLen; i++) {
    fittedPoints.push([
        data[i][0],
        a * pow(data[i][0], b)
    ]);
  }

  return fittedPoints;
}

然后将函数应用于数据。

示例:http://jsfiddle.net/fa3m4Lvf/

当然,如果你的数据不干净,那么你可以通过处理空值等来改进功能

对于那些像我一样正在寻找上述 morganfree 答案的 C# 版本的人,这里是翻译的:

public static IEnumerable<double> GetPowerTrendline(IList<double> knownY, IList<double> knownX, IList<double> newX)
{
    var sums = new double[4];
    var trendlinePoints = new List<double>();
    var dataLen = knownX.Count;

    for (var i = 0; i < dataLen; i++)
    {
        var logX = Math.Log(knownX[i]);
        var logY = Math.Log(knownY[i]);
        sums[0] += logX;
        sums[1] += logY;
        sums[2] += logX * logY;
        sums[3] += Math.Pow(logX, 2);
    }

    var b = (dataLen * sums[2] - sums[0] * sums[1]) / (dataLen * sums[3] - Math.Pow(sums[0], 2));
    var a = Math.Pow(Math.E, (sums[1] - b * sums[0]) / dataLen);

    foreach (var x in newX)
    {
        var pointY = a * Math.Pow(x, b);
        trendlinePoints.Add(pointY);
    }
    return trendlinePoints;
}

请注意,它已被修改,因此它采用所需 x 点的列表而不是使用提供的点。

我按照这个例子计算:http://www.statisticshowto.com/how-to-find-a-linear-regression-equation/

基于此修改了 Adams 示例,并为 C# 提出了此解决方案。这是假设您拥有所有现有的散点图。结果是一些数组列表,其中包含趋势线的所有 x 和 y 值,您可以直接将其插入高图。

public static List<ArrayList> GetPowerTrendline(List<KeyValuePair<int,double>> xyValues)
    {
        var trendlinePoints = new List<ArrayList>();
        var dataLen = xyValues.Count;

        var xSum = xyValues.Sum(h => h.Key);
        var ySum = xyValues.Sum(h => h.Value);
        var XYSum = xyValues.Sum(h => h.Key * h.Value);
        var xp2Sum = xyValues.Sum(x => Math.Pow(x.Key, 2));

        var a = (ySum * xp2Sum - xSum * XYSum) / (dataLen * xp2Sum - Math.Pow(xSum, 2));

        var b = ((dataLen * XYSum) - (xSum * ySum)) / (dataLen * xp2Sum - Math.Pow(xSum,2));

        foreach (var x in xyValues.OrderBy(h => h.Key))
        {
            var pointY = a  + b * x.Key;
            var rounded = Math.Round(pointY, 2);
            trendlinePoints.Add(new ArrayList { x.Key, rounded });
        }
        return trendlinePoints;
    }

在我的 HighCharts 方法中是这样的:

series: [
        {
            type: 'line',
            name: 'Trendlinje',
            data: data.RegressionLine,
            color: '#444444',
            marker: {
                enabled: false
            },
            states: {
                hover: {
                    lineWidth: 0
                }
            },
            enableMouseTracking: false
        },