可同时用 df.max(axis=1) 和 df.idxmax(axis=1) 获取每行最大值及对应列名,二者天然对齐;默认跳过 nan,但全 nan 行会导致 idxmax 报错,需用自定义函数或预过滤处理。

用 idxmax 和 max 一次性拿到列名和值
直接调 df.max(axis=1) 只能拿到每行最大值,df.idxmax(axis=1) 只能拿到对应列名。但这两个结果天然对齐,可以一起用:
result = pd.DataFrame({
'max_value': df.max(axis=1),
'max_column': df.idxmax(axis=1)
})注意:如果某行有多个相同最大值,idxmax 默认返回第一个匹配列名(按列顺序),不会报错也不会警告。
遇到 NaN 怎么办?默认行为可能出人意料
max 和 idxmax 默认会跳过 NaN(skipna=True),但如果整行全是 NaN,max 返回 nan,idxmax 报 ValueError: attempt to get argmax of an empty sequence。解决办法是显式加 skipna=False 并捕获异常,或提前用 df.dropna(how='all') 过滤——但更稳妥的是用 apply + 自定义函数:
def safe_row_max(row):
non_null = row.dropna()
if len(non_null) == 0:
return pd.Series({'max_value': np.nan, 'max_column': None})
idx = non_null.idxmax()
return pd.Series({'max_value': non_null[idx], 'max_column': idx})
result = df.apply(safe_row_max, axis=1)
性能差异:apply 比向量化慢得多,别无脑用
上面的 apply 写法可读性强、容错好,但实测在万行量级 DataFrame 上比纯向量化慢 5–10 倍。如果确认数据不含全 NaN 行,优先用第一种方法;如果必须处理脏数据且性能敏感,先用 df.notna().any(axis=1) 掩码过滤再批量计算,比逐行 apply 快得多。idxmax 对 category 类型列支持有限,遇到会自动转为 object,列名类型可能意外变化。
列名含空格或特殊字符时,idxmax 返回的就是原始字符串
不用额外处理,idxmax 返回的列名就是你在 df.columns 里定义的原样字符串,包括空格、点号、中文等。但要注意:如果后续要用这个列名做索引(比如 df.loc[row, col_name]),确保没拼错——尤其当列名是数字字符串(如 '2023')时,别误以为是整数索引。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











