如何基于Pandas DataFrame非NaN值的列名生成新列Mode?
高效解决方案
你可以利用Pandas的矢量化操作实现需求,完全规避拆分合并这类低效方式,核心思路是通过布尔矩阵筛选每行非NaN值对应的列名,再进行拼接:
import pandas as pd import numpy as np # 构造示例DataFrame df = pd.DataFrame({ 'subsegment': ['corp', np.nan, 'terr'], 'region': ['japan', np.nan, np.nan], 'subregion': [np.nan, 'se', 'ne'], 'segment': [np.nan,'ent','comm'] }) # 生成mode列 df['mode'] = df.notna().apply(lambda row: '-'.join(df.columns[row]), axis=1)
代码解释
df.notna():生成与原DataFrame结构一致的布尔矩阵,每个元素标记对应位置的值是否为非NaN。apply(..., axis=1):逐行处理布尔矩阵,row代表每行的布尔Series。df.columns[row]:筛选出该行中值为True(即原DataFrame对应位置非NaN)的列名。'-'.join(...):将筛选出的列名用连字符-连接成字符串,赋值给mode列。
大数据量优化方案(纯矢量化)
如果处理的数据集规模极大,还可以用stack实现纯矢量化操作,进一步降低apply的逐行遍历开销:
# 保留非NaN值,将NaN值替换后堆叠 stacked = df.mask(df.isna()).stack() # 按行分组,拼接每行对应的列名 df['mode'] = stacked.groupby(level=0).apply(lambda x: '-'.join(x.index.get_level_values(1)))
最终生成的结果:
| subsegment | region | subregion | segment | mode |
|---|---|---|---|---|
| corp | japan | NaN | NaN | subsegment-region |
| NaN | NaN | se | ent | subregion-segment |
| terr | NaN | ne | comm | subsegment-subregion-segment |
内容的提问来源于stack exchange,提问作者mtm1186
相关产品推荐
相关产品推荐

