如何合并含重叠ID的Pandas DataFrame并按规则整理数值
Pandas合并多个DataFrame:保留非零值并去重零值样本
问题背景
我有三个Pandas DataFrame:
import pandas as pd # 定义样本名称为字符串(避免未定义变量报错) Sample1, Sample2, Sample3, Sample4 = "Sample1", "Sample2", "Sample3", "Sample4" df1 = pd.DataFrame({'sample': [Sample1, Sample2, Sample3, Sample4], 'value': [0.00, 0.0, 0.1, 0.0]}) df2 = pd.DataFrame({'sample': [Sample1, Sample2, Sample3, Sample4], 'value': [0.00, 0.2, 0.5, 0.0]}) df3 = pd.DataFrame({'sample': [Sample1, Sample2, Sample3, Sample4], 'value': [0.00, 0.3, 0.6, 0.0]})
对应的表格分别为:
Table A(df1)
| sample | value |
|---|---|
| Sample1 | 0.0 |
| Sample2 | 0.0 |
| Sample3 | 0.1 |
| Sample4 | 0.0 |
Table B(df2)
| sample | value |
|---|---|
| Sample1 | 0.0 |
| Sample2 | 0.2 |
| Sample3 | 0.5 |
| Sample4 | 0.0 |
Table C(df3)
| sample | value |
|---|---|
| Sample1 | 0.0 |
| Sample2 | 0.3 |
| Sample3 | 0.6 |
| Sample4 | 0.0 |
需要合并这三个DataFrame,满足以下要求:
- 所有大于0.00的值保留,且对应的样本名添加对应表格后缀(_A/_B/_C)
- 每个原始样本ID的0.00值仅显示一次,不需要重复保留
预期输出如下:
Sample1 0.0 Sample2_B 0.2 Sample2_C 0.3 Sample3_A 0.1 Sample3_B 0.5 Sample3_C 0.6 Sample4 0.0
(注:预期输出中的Sample2_A 0.0是不需要的)
解决方案
可以通过以下步骤实现需求:
步骤1:给每个DataFrame的样本名添加标识后缀
为区分不同来源的记录,给每个df的sample列添加对应后缀:
df1['sample'] = df1['sample'] + '_A' df2['sample'] = df2['sample'] + '_B' df3['sample'] = df3['sample'] + '_C'
步骤2:合并三个DataFrame
使用pd.concat合并处理后的DataFrame:
combined_df = pd.concat([df1, df2, df3], ignore_index=True)
步骤3:筛选并整理记录
- 从带后缀的样本名中提取原始名称(比如
Sample2_A提取为Sample2) - 筛选所有非零值记录,以及每个原始样本的第一条零值记录:
# 提取原始样本名作为辅助列 combined_df['original_sample'] = combined_df['sample'].str.split('_').str[0] # 筛选非零值记录 non_zero = combined_df[combined_df['value'] > 0] # 筛选每个原始样本的第一条零值记录,并将样本名改回原始名称 zero_records = combined_df[combined_df['value'] == 0].drop_duplicates(subset='original_sample', keep='first') zero_records['sample'] = zero_records['original_sample']
步骤4:合并结果并格式化
合并非零值和去重后的零值记录,移除辅助列并排序:
final_df = pd.concat([non_zero, zero_records], ignore_index=True).drop('original_sample', axis=1) final_df = final_df.sort_values('sample').reset_index(drop=True)
完整代码
import pandas as pd # 定义样本名称字符串 Sample1, Sample2, Sample3, Sample4 = "Sample1", "Sample2", "Sample3", "Sample4" # 创建原始DataFrame df1 = pd.DataFrame({'sample': [Sample1, Sample2, Sample3, Sample4], 'value': [0.00, 0.0, 0.1, 0.0]}) df2 = pd.DataFrame({'sample': [Sample1, Sample2, Sample3, Sample4], 'value': [0.00, 0.2, 0.5, 0.0]}) df3 = pd.DataFrame({'sample': [Sample1, Sample2, Sample3, Sample4], 'value': [0.00, 0.3, 0.6, 0.0]}) # 1. 添加后缀 df1['sample'] = df1['sample'] + '_A' df2['sample'] = df2['sample'] + '_B' df3['sample'] = df3['sample'] + '_C' # 2. 合并DataFrame combined_df = pd.concat([df1, df2, df3], ignore_index=True) # 3. 处理零值和非零值 combined_df['original_sample'] = combined_df['sample'].str.split('_').str[0] non_zero = combined_df[combined_df['value'] > 0] zero_records = combined_df[combined_df['value'] == 0].drop_duplicates(subset='original_sample', keep='first') zero_records['sample'] = zero_records['original_sample'] # 合并结果并清理 final_df = pd.concat([non_zero, zero_records], ignore_index=True).drop('original_sample', axis=1) final_df = final_df.sort_values('sample').reset_index(drop=True) # 输出结果 print(final_df)
运行后输出:
sample value 0 Sample1 0.0 1 Sample2_B 0.2 2 Sample2_C 0.3 3 Sample3_A 0.1 4 Sample3_B 0.5 5 Sample3_C 0.6 6 Sample4 0.0
内容的提问来源于stack exchange,提问作者honeymoon
相关产品推荐
相关产品推荐

