计算特征向量中心性与壳指数的斯皮尔曼相关性时抛出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
相关产品推荐
相关产品推荐

