Pandas如何清理含NaN的DataFrame并按Statement合并STAN列数据
问题描述
我有一个多列包含NaN值的DataFrame,其中“STAN-x”列的数据仅需与对应的“Statement”匹配,且可去除重复的Statement取值。
原始DataFrame数据
Statement STAN-A STAN-B STAN-C STAN-D STAN-E STAN-F 0 Statement A AB.AM-1 ABC ABC 1 NaN NaN NaN NaN 1 Statement A AB.AM-1 NaN ABCDE 5 ABCDE.01 NaN NaN NaN 1 Statement A AB.AM-1 NaN ABCDE 5 ABCDE.02 NaN NaN NaN 2 Statement A AB.AM-1 NaN NaN ABC 62443-2-1:2009 4.2.3.4 NaN NaN 3 Statement A AB.AM-1 NaN NaN ABC 62443-3-3:2013 SR 7.8 NaN NaN 4 Statement A AB.AM-1 NaN NaN NaN ABC/ABC 27001:2013 A.8.1.1 NaN 4 Statement A AB.AM-1 NaN NaN NaN A.8.1.2 NaN 5 Statement A AB.AM-1 NaN NaN NaN NaN ABCD AB 800-53 Rev. 4 CM-8 5 Statement A AB.AM-1 NaN NaN NaN NaN PM-5 6 Statement B AB.AM-2 ABC ABC 2 NaN NaN NaN NaN 7 Statement B AB.AM-2 NaN ABCDE 5 ABCDE.01 NaN NaN NaN 7 Statement B AB.AM-2 NaN ABCDE 5 ABCDE.02 NaN NaN NaN 7 Statement B AB.AM-2 NaN ABCDE 5 ABCDE.05 NaN NaN NaN 8 Statement B AB.AM-2 NaN NaN ABC 62443-2-1:2009 4.2.3.4 NaN NaN 9 Statement B AB.AM-2 NaN NaN ABC 62443-3-3:2013 SR 7.8 NaN NaN 10 Statement B AB.AM-2 NaN NaN NaN ABC/ABC 27001:2013 A.8.1.1 NAN 11 Statement B AB.AM-2 NaN NaN NaN NAN ABCD AB 800-53 Rev. 5 CM-9
预期输出结果
Statement STAN-A STAN-B STAN-C STAN-D STAN-E STAN-F 0 Statement A AB.AM-1 ABC ABC 1 ABCDE 5 ABCDE.01 ABC 62443-2-1:2009 4.2.3.4 ABC/ABC 27001:2013 A.8.1.1 ABCD AB 800-53 Rev. 4 CM-8 1 Statement A AB.AM-1 NaN ABCDE 5 ABCDE.02 ABC 62443-3-3:2013 SR 7.8 A.8.1.2 PM-5 2 Statement A AB.AM-1 NaN NaN ABC 62443-2-1:2009 4.2.3.4 NaN NaN 3 Statement B AB.AM-2 ABC ABC 2 ABCDE 5 ABCDE.01 ABC 62443-2-1:2009 4.2.3.4 ABC/ABC 27001:2013 A.8.1.1 ABCD AB 800-53 Rev. 5 CM-9 4 Statement B AB.AM-2 NaN ABCDE 5 ABCDE.02 ABC 62443-3-3:2013 SR 7.8 NaN NaN 5 Statement B AB.AM-2 NaN ABCDE 5 ABCDE.05 NaN NaN NaN
已尝试的方案
- 执行
df.dropna(),执行后所有数据都被清空,原因是该方法默认会删除包含任意NaN的行,原始数据每行都存在NaN,因此全部被删除 - 执行以下代码:
df.assign(**{'STAN-B': df['STAN-B'].join(df['STAN-B'].dropna())})
返回报错:
AttributeError: 'Series' object has no attribute 'join'
报错原因是join是DataFrame专属方法,Series对象不支持该调用。
实现代码
import pandas as pd import numpy as np # 提取所有STAN开头的列名 stan_cols = [col for col in df.columns if col.startswith('STAN-')] result_list = [] # 按Statement分组独立处理 for statement, group_df in df.groupby('Statement'): # 收集当前分组下所有STAN列的非空值 col_data = {} for col in stan_cols: # 提取非空值并重置索引,方便后续横向对齐 non_na_vals = group_df[col].dropna().reset_index(drop=True) col_data[col] = non_na_vals # 合并当前Statement的所有列,短列自动补NaN current_stmt_df = pd.DataFrame(col_data) current_stmt_df['Statement'] = statement result_list.append(current_stmt_df) # 合并所有分组结果,调整列顺序与原始一致 final_df = pd.concat(result_list, ignore_index=True)[df.columns]
逻辑说明
- 按
Statement字段拆分不同分组,避免不同Statement的数据互相干扰 - 对每个分组内的每个STAN列,仅保留非空值,重新按0、1、2的顺序设置索引
- 同一分组下处理后的所有STAN列横向拼接,长度较短的列末尾会自动填充NaN
- 合并所有Statement的处理结果,调整列顺序即可得到目标输出
内容的提问来源于stack exchange,提问作者clines
相关产品推荐
相关产品推荐

