9

我有 2 个长度相等的数组。以下函数尝试使用这些数组计算斜率。它返回每个点之间的斜率的平均值。对于以下数据集,我似乎得到了与 Excel 和 Google Docs 不同的值。

        double[] x_values = { 1932, 1936, 1948, 1952, 1956, 1960, 1964, 1968,
            1972, 1976, 1980 };
    double[] y_values = { 197, 203, 198, 204, 212, 216, 218, 224, 223, 225,
            236 };



public static double getSlope(double[] x_values, double[] y_values)
        throws Exception {

    if (x_values.length != y_values.length)
        throw new Exception();

    double slope = 0;

    for (int i = 0; i < (x_values.length - 1); i++) {
        double y_2 = y_values[i + 1];
        double y_1 = y_values[i];

        double delta_y = y_2 - y_1;

        double x_2 = x_values[i + 1];
        double x_1 = x_values[i];

        double delta_x = x_2 - x_1;

        slope += delta_y / delta_x;
    }

    System.out.println(x_values.length);
    return slope / (x_values.length);
}

输出

谷歌:0.755

getSlope(): 0.962121212121212

Excel:0.7501

4

4 回答 4

5

我敢打赌,其他两种方法正在计算最小二乘拟合,而您不是。

当我使用R验证这个猜想时,我也得到了大约 0.755 的斜率:

> summary(lm(y~x))

Call:
lm(formula = y ~ x)

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -1.265e+03  1.793e+02  -7.053 5.97e-05 ***
x            7.551e-01  9.155e-02   8.247 1.73e-05 ***

相关号码是7.551e-01。还值得注意的是,这条线的截距约为 -1265。

这是最小二乘拟合的图片:

适合

至于在您的代码中实现这一点,请参阅使用 java 计算最小二乘

于 2013-03-15T12:30:15.857 回答
2

这个函数对你帮助不大,因为它没有考虑到各个线段的宽度。考虑将其应用于点 (0,0)、(1000,1000) 和 (1001, 2000) 与 (0,0)、(1,1) 和 (2, 1001) 之间的差异。这两种情况都有连续的斜率 1 和 1000,但它们看起来却大不相同。

您需要实现最小二乘法:http ://en.wikipedia.org/wiki/Least_squares以找到最接近您的数据集的线。

还有一条建议:永远不要抛出java.lang.Exception. 始终选择更具体的异常,即使您必须自己编写类。使用您的代码的人将需要处理java.lang.Exception,这会严重干扰他们的其他代码。

于 2013-03-15T12:24:01.807 回答
0

编辑:如果可以的话,使用 Apache Commons Math 类SimpleRegression 。否则,这是一种计算斜率和截距的方法,应该产生与 excel 和 apache 相同的结果:

private static double intercept(List<Double> yList, List<Double> xList) {
    if (yList.size() != xList.size())
        throw new IllegalArgumentException("Number of y and x must be the same");
    if (yList.size() < 2)
        throw new IllegalArgumentException("Need at least 2 y, x");

    double yAvg = average(yList);
    double xAvg = average(xList);

    double sumNumerator = 0d;
    double sumDenominator = 0d;
    for (int i = 0; i < yList.size(); i++) {
        double y = yList.get(i);
        double x = xList.get(i);
        double yDiff = y - yAvg;
        double xDiff = x - xAvg;
        double numerator = xDiff * yDiff;
        double denominator = xDiff * xDiff;
        sumNumerator += numerator;
        sumDenominator += denominator;
    }

    double slope = sumNumerator / sumDenominator;
    double intercept = yAvg - (slope * xAvg);
    return intercept;
}

private static double average(Collection<Double> doubles) {
    return doubles.stream().collect(Collectors.averagingDouble(d -> d));
}

资料来源: Excel doc for SLOPE Excel doc for INTERCEPT

于 2020-04-24T10:37:23.137 回答
-1

你应该除以x_values.length - 1。斜率的数量是成对的。

编辑:我评论中的 Wiki 示例显示了如何计算确定线性回归线斜率的 alpha 和 beta。

于 2013-03-15T12:04:45.720 回答