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

计算特征向量中心性与壳指数的斯皮尔曼相关性时抛出NotANumberException,求实现返回0.0的解决方案

计算特征向量中心性与壳指数的斯皮尔曼相关性时抛出NotANumberException,求实现返回0.0的解决方案

嘿,我看了你的问题和控制台输出,问题根源很明确:所有的特征向量中心性值都是0.01,导致归一化计算时出现除以零的情况,生成了NaN值,而Apache Commons Math的SpearmansCorrelation无法处理NaN,所以抛出了NotANumberException。

我们可以分两步来解决这个问题,既避免NaN的产生,又在数据无波动时返回0.0的相关性结果:

1. 修复归一化逻辑,避免除以零

在CentralitiesAnalyzer的insertValues方法中,当所有ys值(特征向量中心性)相同时,min和max会相等,此时(ys[i] - min)/(max - min)会得到NaN。我们需要先判断这种情况,直接将所有ys值设为0.0:

protected void insertValues() {
    double min = Arrays.stream(ys).min().getAsDouble();
    double max = Arrays.stream(ys).max().getAsDouble();

    // 处理所有特征向量中心性值相同的情况,避免除以零生成NaN
    if (Double.compare(min, max) == 0) {
        Arrays.fill(ys, 0.0);
    } else {
        for (int i = 0; i < vertices.length; i++) {
            ys[i] = (ys[i] - min) / (max - min);
        }
    }

    // 填充结果列表
    for (int i = 0; i < vertices.length; i++) {
        String id = vertices[i].getId();
        double x = xs[i];
        double y = ys[i];
        results.add(new Triple<>(id, x, y));
    }

    // 计算斯皮尔曼相关性
    SpearmansCorrelation sc = new SpearmansCorrelation();
    try {
        correlation = sc.correlation(xs, ys);
    } catch (NotANumberException | IllegalArgumentException e) {
        // 当数据无波动时(比如所有值相同),相关性为0.0
        correlation = 0.0;
    }
}

2. 提前检查数据波动,优雅避免异常

如果你不想依赖异常捕获,还可以提前检查xs(壳指数)或ys是否所有值都相同。如果任意一组数据无波动,斯皮尔曼相关性必然为0.0,直接赋值即可:

protected void insertValues() {
    double min = Arrays.stream(ys).min().getAsDouble();
    double max = Arrays.stream(ys).max().getAsDouble();

    // 处理归一化
    if (Double.compare(min, max) == 0) {
        Arrays.fill(ys, 0.0);
    } else {
        for (int i = 0; i < vertices.length; i++) {
            ys[i] = (ys[i] - min) / (max - min);
        }
    }

    // 填充结果列表
    for (int i = 0; i < vertices.length; i++) {
        String id = vertices[i].getId();
        double x = xs[i];
        double y = ys[i];
        results.add(new Triple<>(id, x, y));
    }

    // 提前检查数据是否有波动
    boolean xsAllSame = Arrays.stream(xs).allMatch(v -> Double.compare(v, xs[0]) == 0);
    boolean ysAllSame = Arrays.stream(ys).allMatch(v -> Double.compare(v, ys[0]) == 0);

    if (xsAllSame || ysAllSame) {
        correlation = 0.0;
    } else {
        SpearmansCorrelation sc = new SpearmansCorrelation();
        correlation = sc.correlation(xs, ys);
    }
}

为什么这样有效?

  • 当所有特征向量中心性值相同时,归一化后的ys会被统一设为0.0,不会产生NaN。
  • 斯皮尔曼相关性衡量的是两个变量的秩相关程度,如果其中一个变量所有值都相同,秩没有变化,相关性自然为0.0。

这样修改后,你的程序就不会再抛出异常,而是在数据无波动时返回0.0作为相关性结果,同时正常导出CSV文件。

备注:内容来源于stack exchange,提问作者IgorArnaut

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 09:30:32