df.max(axis=1)返回NaN仅当某行全为NaN;默认skipna=True但需至少一个非空值,整行为空时无定义。

为什么 df.max(axis=1) 有时返回 NaN 而不是数字
因为只要某一行中任意一列是 NaN,max() 默认不跳过它(skipna=True 是默认值,但前提是该行至少有一个非空值)。真正出问题的是整行全为 NaN —— 此时 max() 无定义,只能返回 NaN。
实操建议:
- 先用
df.dropna(how='all')清理全空行,或用df.fillna(-float('inf'))把空值垫底(注意业务含义) - 确认参与计算的列:别直接对含字符串列的 DataFrame 调用
max(axis=1),会报TypeError: max() is not supported for this dtype - 若只关心数值列,显式传入:
df.select_dtypes(include='number').max(axis=1)
用 apply() + max 替代 max(axis=1) 的真实代价
表面上更灵活,比如可以写 df.apply(lambda x: max(x.dropna()), axis=1),但性能差一个数量级。Pandas 的 max(axis=1) 是底层 Cython 实现,而 apply 是 Python 循环。
实操建议:
- 99% 场景坚持用
max(axis=1),它足够健壮 - 只有当需要混合类型比较、或自定义忽略规则(如忽略负数)时,才考虑
apply,并提前用numba.jit或向量化逻辑重写 - 测试时对比耗时:对 10 万行 × 10 列数据,
max(axis=1)通常在 5ms 内,apply(..., axis=1)可能超过 300ms
max(axis=1) 在多索引 DataFrame 中的行为
它完全不关心索引层级,只按行物理位置算最大值。如果行索引有重复或非连续,结果顺序仍严格对应原始 iloc 顺序。
实操建议:
- 若需按某个索引层级分组后取每组内各行最大值,不要用
axis=1,改用groupby(level=...).apply(lambda x: x.max(axis=1)) - 多索引列下,
max(axis=1)会把所有列扁平化处理,不区分二级列名;如有列名冲突(如多个('A', 'val')),会静默合并 —— 建议先用df.columns = df.columns.map('_'.join)去重
和 numpy.max 混用时的隐式类型转换陷阱
当你写 np.max(df.values, axis=1),Pandas 会先把 DataFrame 转成 ndarray,此时如果列类型不一致(比如混了 int64 和 float64),整个数组会升格为 object 类型,np.max 直接抛错:TypeError: unorderable types: str() > int()。
实操建议:
- 避免直接对
df.values调np.max;优先用 Pandas 原生方法 - 非要转 numpy,先统一类型:
df.astype(float).values,再调np.max(..., axis=1) - 注意
np.max默认不跳过NaN,必须显式加keepdims=False和initial=-np.inf才等价于 Pandas 行为

















