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

使用df.corrwith(axis=1)计算行Pearson相关系数返回空值排查

解决pandas corrwith(axis=1)返回空值的问题

我碰到过好几个用户遇到同样的问题——以为corrwith(axis=1)会逐行计算两个DataFrame的Pearson相关系数,结果却全是NaN,但Excel的CORREL却能算出值。这里的问题大概率出在pandas corrwith的行为逻辑或者数据对齐/格式上,咱们一步步拆解解决:

为什么你的corrwith返回空值?

先搞清楚corrwith(axis=1)的真实作用:它要求两个DataFrame的行索引完全匹配,且列数一致,然后才会计算每一行对应位置的系列相关系数。如果满足不了这两个前提,或者每行数据存在以下情况,就会返回NaN:

  • 两个DataFrame的行索引不匹配,对齐后没有重叠的行;
  • 某一行的两个系列(df_A的行和df_B的行)中有一个/两个的方差为0(比如整行都是同一个值);
  • 某一行的非NaN值不足2个,无法计算相关系数;
  • 列数不一致,导致无法生成等长的系列来计算相关系数。

而Excel的CORREL会自动忽略单元格中的NaN,且只要有至少2对非空值就能计算,这也是它能出结果的原因。

解决方案:用更可靠的逐行计算方式

与其依赖corrwith的对齐逻辑,不如直接手动实现逐行的Pearson相关系数计算,这样更可控:

方法1:用scipy.stats逐行计算(易读性高)

import pandas as pd
import scipy.stats as stats

# 先确保两个DataFrame的行索引一致(重置索引避免对齐问题)
df_A = df_A.reset_index(drop=True)
df_B = df_B.reset_index(drop=True)

def calculate_row_corr(row_a, row_b):
    # 过滤掉两行中任意一个为NaN的位置
    valid_mask = ~row_a.isna() & ~row_b.isna()
    filtered_a = row_a[valid_mask]
    filtered_b = row_b[valid_mask]
    
    # 至少需要2个有效数据点才能计算相关系数
    if len(filtered_a) < 2:
        return None
    
    # 检查方差是否为0(避免除以0错误)
    if filtered_a.var() == 0 or filtered_b.var() == 0:
        return None
    
    # 返回Pearson相关系数(scipy的pearsonr返回系数和p值,取第一个)
    return stats.pearsonr(filtered_a, filtered_b)[0]

# 逐行应用函数生成结果
corr_series = pd.Series(
    [calculate_row_corr(df_A.iloc[i], df_B.iloc[i]) for i in range(len(df_A))],
    index=df_A.index,
    name="Pearson_Correlation"
)

方法2:用numpy批量计算(效率更高,适合大数据集)

如果你的DataFrame行数很多,用循环会比较慢,可以用numpy实现向量化计算:

import pandas as pd
import numpy as np

# 转换为numpy数组
a_np = df_A.to_numpy()
b_np = df_B.to_numpy()

# 计算每行的均值(忽略NaN)
mean_a = np.nanmean(a_np, axis=1, keepdims=True)
mean_b = np.nanmean(b_np, axis=1, keepdims=True)

# 计算协方差分子
covariance = np.nansum((a_np - mean_a) * (b_np - mean_b), axis=1)

# 计算标准差的乘积(分母)
std_a = np.sqrt(np.nansum((a_np - mean_a)**2, axis=1))
std_b = np.sqrt(np.nansum((b_np - mean_b)**2, axis=1))

# 计算相关系数,处理分母为0的情况(返回NaN)
corr_array = np.where((std_a == 0) | (std_b == 0), np.nan, covariance / (std_a * std_b))

# 转换为pandas Series
corr_series = pd.Series(corr_array, index=df_A.index, name="Pearson_Correlation")

验证结果是否和Excel一致

运行上面的代码后,你可以取几行和Excel的CORREL结果对比,应该就能匹配上了。如果还是有差异,检查一下:

  • 是否Excel中某些行的NaN被你手动忽略了?
  • 两个DataFrame的对应行数据是否完全一致(比如有没有导入时的格式错误)?

内容的提问来源于stack exchange,提问作者Gautham Kanthasamy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:32:26