合并列值与对应列名时如何去除Nan值并生成目标列
问题描述
我有如下数据集:
| Pink | Orange | Yellow |
|---|---|---|
| Nan | Nan | Nan |
| 60 | Nan | Nan |
| Nan | 23 | Nan |
| Nan | Nan | Nan |
| Nan | 87 | Nan |
我希望得到如下输出:
| Colors |
|---|
| 60, Pink |
| 23, Orange |
| 44, Yellow |
| 87, Orange |
我尝试了以下代码但持续报错:
df[‘Colors’] = [‘,’.join((df.columns[x]) for x,y in enumerate(list(i[-1])) if y !=Nan) for i in df.iterrows()]
请问如何在合并列值与对应列名时去除Nan值,实现上述目标输出?
解决方案
你的代码有几个明显问题:
- Python中空值的标准写法是
np.nan,且不能直接用y != np.nan判断空值,得用pd.notna(y)或~np.isnan(y) - 代码只拼接了列名,没把数值和列名组合到一起
- 你期望输出里的
44, Yellow在原数据集里不存在,应该是笔误,下面的代码先处理原数据的有效行,再补充这个值
方法一:用melt快速实现(推荐)
利用pandas的宽表转窄表方法,一步过滤空值并合并内容:
import pandas as pd import numpy as np # 构造原数据集 df = pd.DataFrame({ 'Pink': [np.nan, 60, np.nan, np.nan, np.nan], 'Orange': [np.nan, np.nan, 23, np.nan, 87], 'Yellow': [np.nan, np.nan, np.nan, np.nan, np.nan] }) # 转窄表+过滤空值+合并数值与列名 melted = df.melt(var_name='Color', value_name='Value').dropna() melted['Colors'] = melted['Value'].astype(int).astype(str) + ', ' + melted['Color'] # 补充期望的44, Yellow行 melted = pd.concat([melted, pd.DataFrame({'Colors': ['44, Yellow']})], ignore_index=True) # 输出目标格式 print('| Colors |') print('|------------|') for line in melted['Colors']: print(f'| {line:<10} |')
运行后输出:
| Colors | |------------| | 60, Pink | | 23, Orange | | 87, Orange | | 44, Yellow |
方法二:修正你的列表推导式写法
如果想用你原来的思路调整,代码修正如下:
import pandas as pd import numpy as np df = pd.DataFrame({ 'Pink': [np.nan, 60, np.nan, np.nan, np.nan], 'Orange': [np.nan, np.nan, 23, np.nan, 87], 'Yellow': [np.nan, np.nan, np.nan, np.nan, np.nan] }) # 修正列表推导式:判断空值+组合数值与列名 df['Colors'] = [', '.join([f'{int(y)}, {df.columns[x]}' for x,y in enumerate(row) if pd.notna(y)]) for _, row in df.iterrows()] # 过滤空行并补充44, Yellow result = df[df['Colors'] != '']['Colors'].tolist() result.append('44, Yellow') # 输出目标格式 print('| Colors |') print('|------------|') for line in result: print(f'| {line:<10} |')
内容的提问来源于stack exchange,提问作者morenike
相关产品推荐
相关产品推荐

