如何在Pandas DataFrame中合并指定列到JSONB格式的champs_addi列并跳过空值?
解决方案:将非空id字段合并到PostgreSQL jsonb格式的champs_addi列
核心思路
要实现把id_1和id_2的非空值合并到champs_addi列(保留原有内容),关键是把champs_addi的JSON字符串转成字典进行操作,完成后再转回JSON格式,适配PostgreSQL的jsonb类型。
完整代码实现
import numpy as np import pandas as pd import json df = pd.DataFrame({ 'nom': ['sireesha', 'ravi', 'rohith', 'pinkey', 'gnanesh'], 'prenom': ['mary', 'jack', 'mark', 'someone', 'anothersomeone'], 'id_1': [98, np.nan, 32, np.nan, 23], 'id_2': [1, 12, 78, np.nan, 87], 'champs_addi': [np.nan, np.nan, '{"statut": "actif"}', np.nan, np.nan], }) # 转换float类型的id列为Int64(支持空值的整数类型) for col in df.columns[df.isna().any()].tolist(): if df[col].dtype == 'float': df[col] = df[col].astype('Int64') # 步骤1:将champs_addi的NaN转为空字典,已有JSON字符串转为Python字典 df['champs_addi'] = df['champs_addi'].apply( lambda x: json.loads(x) if pd.notna(x) else {} ) # 步骤2:为每行生成仅包含非空id的字典 id_entries = df[['id_1', 'id_2']].apply( lambda row: {k: v for k, v in row.items() if pd.notna(v)}, axis=1 ) # 步骤3:合并原有champs_addi字典和id字典 df['champs_addi'] = df.apply( lambda row: {**row['champs_addi'], **id_entries[row.name]}, axis=1 ) # 步骤4:将字典转回JSON字符串,空字典转为NaN(适配PostgreSQL jsonb的null) df['champs_addi'] = df['champs_addi'].apply( lambda x: json.dumps(x) if x else np.nan ) # 查看最终结果 print(df)
代码说明
- 类型转换:先把float类型的id列转为
Int64,确保空值用pd.NA而非np.nan,后续非空判断更准确。 - JSON转字典:把
champs_addi的JSON字符串解析成Python字典,方便修改合并;空值直接转为空字典。 - 生成非空id字典:遍历每行,只保留
id_1和id_2中非空的键值对,避免把NA值写入JSON。 - 字典合并:用字典解包的方式,把id键值对合并到原有
champs_addi字典中,自动覆盖重复键(如果存在)。 - 转回JSON字符串:合并后的字典重新转为JSON字符串,空字典转为
np.nan,插入PostgreSQL时会被识别为jsonb类型的null。
最终输出示例
处理后的df中champs_addi列内容如下:
- 第1行:
{"id_1": 98, "id_2": 1} - 第2行:
{"id_2": 12} - 第3行:
{"statut": "actif", "id_1": 32, "id_2": 78} - 第4行:
NaN - 第5行:
{"id_1": 23, "id_2": 87}
这样处理后的DataFrame可直接插入目标PostgreSQL数据库,champs_addi列格式完全符合jsonb类型要求。
内容的提问来源于stack exchange,提问作者ml_cen
相关产品推荐
相关产品推荐

