如何高效拆分Pandas DataFrame行:每行仅保留一个非NaN值
Pandas 按规则拆分DataFrame(避免逐行迭代)
核心思路
通过分离固定列+融化拆分列+重组数据的向量式操作实现需求,全程避免逐行迭代,保证处理大数据时的性能:
- 把
Schema、Column、Trh1、Trh2设为固定列,其中Trh1和Trh2可同时非空,作为一组保留; - 将
Trh3及后续所有需要拆分的列转成键值对,提取非NaN值并重组为单独行——这些行里Trh1和Trh2设为NaN,仅保留对应Trh列的非空值; - 合并两部分数据,得到最终结果。
代码实现
import pandas as pd import numpy as np # 示例输入数据 df = pd.DataFrame({ 'Schema': ['schema_1', 'schema_2', 'schema_3', 'schema_4'], 'Column': ['col_1', 'col_2', 'col_3', 'col_4'], 'Trh1': [np.nan, 0.02, 0.03, np.nan], 'Trh2': [0.01, 0.03, 0.04, np.nan], 'Trh3': [np.nan, np.nan, 0.05, 0.06], 'Trh4': [np.nan, np.nan, np.nan, 0.07] }) # 定义固定列和需要拆分的列 special_cols = ['Schema', 'Column', 'Trh1', 'Trh2'] split_cols = [col for col in df.columns if col not in special_cols] # 第一步:生成保留Trh1/Trh2的行(拆分列置空) df_trh_pair = df[df[['Trh1', 'Trh2']].notna().any(axis=1)].copy() df_trh_pair[split_cols] = np.nan # 第二步:处理拆分列,生成单个Trh值的行 # 融化拆分列为键值对,过滤空值 melted_trh = df.melt( id_vars=special_cols, value_vars=split_cols, var_name='trh_column', value_name='trh_value' ).dropna(subset=['trh_value']) # 构造拆分后的DataFrame df_single_trh = pd.DataFrame() # 保留Schema和Column df_single_trh[['Schema', 'Column']] = melted_trh[['Schema', 'Column']] # Trh1和Trh2置空 df_single_trh[['Trh1', 'Trh2']] = np.nan # 为每个Trh列填充对应的值 for col in split_cols: mask = melted_trh['trh_column'] == col df_single_trh.loc[mask, col] = melted_trh.loc[mask, 'trh_value'] # 合并结果并重置索引 final_df = pd.concat([df_trh_pair, df_single_trh], ignore_index=True) # 按Schema和Column排序,匹配示例输出顺序 final_df = final_df.sort_values(by=['Schema', 'Column']).reset_index(drop=True) print(final_df)
输出结果
Schema Column Trh1 Trh2 Trh3 Trh4 0 schema_1 col_1 NaN 0.01 NaN NaN 1 schema_2 col_2 0.02 0.03 NaN NaN 2 schema_3 col_3 0.03 0.04 NaN NaN 3 schema_3 col_3 NaN NaN 0.05 NaN 4 schema_4 col_4 NaN NaN 0.06 NaN 5 schema_4 col_4 NaN NaN NaN 0.07
适配多列场景
代码中split_cols会自动识别所有非固定列,无论实际有多少个Trh列(Trh3、Trh4...TrhN),都能自动处理,无需修改核心逻辑。
内容的提问来源于stack exchange,提问作者Slawek
相关产品推荐
相关产品推荐

