我需要在代码中复制这个 Excel 图表
给定一个 [x, y] 值列表,我如何获得一个新的值列表来绘制功率趋势线?
我发现人们指的是这个http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html公式。但不知道如何从中生成新的值列表。
我需要在代码中复制这个 Excel 图表
给定一个 [x, y] 值列表,我如何获得一个新的值列表来绘制功率趋势线?
我发现人们指的是这个http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html公式。但不知道如何从中生成新的值列表。
按照链接中的公式:
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 值,您可以直接插入到 highcharts 中。
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
},