含不同缺失行的DataFrame中不确定度传递及零值排除方法问询
解决方案:多DataFrame零值过滤与不确定度传递合并
核心思路
针对不同区域的DataFrame,我们需要先过滤零值(缺失数据),利用uncertainties库自动处理不确定度传递,再按x分组加权平均,最终合并所有区域数据得到单条曲线。
步骤实现
1. 导入依赖库
import pandas as pd import numpy as np from uncertainties import unumpy as unp
2. 单DataFrame处理函数
该函数负责过滤零值、计算单区域内的加权平均及净信号:
def process_single_df(df): # 分离样本(s)、背景(b)及其误差列 s_cols = [col for col in df.columns if col.startswith('s') and '_err' not in col] s_err_cols = [col for col in df.columns if col.startswith('s_err')] b_cols = [col for col in df.columns if col.startswith('b') and '_err' not in col] b_err_cols = [col for col in df.columns if col.startswith('b_err')] # 收集所有非零样本数据 s_valid = [] for s_col, err_col in zip(s_cols, s_err_cols): mask = df[s_col] != 0 filtered = df.loc[mask, ['x', s_col, err_col]] filtered.columns = ['x', 'value', 'err'] s_valid.append(filtered) s_all = pd.concat(s_valid, ignore_index=True) # 收集所有非零背景数据 b_valid = [] for b_col, err_col in zip(b_cols, b_err_cols): mask = df[b_col] != 0 filtered = df.loc[mask, ['x', b_col, err_col]] filtered.columns = ['x', 'value', 'err'] b_valid.append(filtered) b_all = pd.concat(b_valid, ignore_index=True) # 定义加权平均计算逻辑(权重为误差方差的倒数) def weighted_avg(group): y_with_err = unp.uarray(group['value'], group['err']) weights = 1 / (group['err'] ** 2) avg = np.sum(y_with_err * weights) / np.sum(weights) return pd.Series({ 'avg_val': unp.nominal_values(avg), 'avg_err': unp.std_devs(avg) }) # 按x分组计算样本、背景的加权平均 s_avg = s_all.groupby('x').apply(weighted_avg).reset_index() s_avg.rename(columns={'avg_val': 's_avg', 'avg_err': 's_avg_err'}, inplace=True) b_avg = b_all.groupby('x').apply(weighted_avg).reset_index() b_avg.rename(columns={'avg_val': 'b_avg', 'avg_err': 'b_avg_err'}, inplace=True) # 合并并计算净信号(样本-背景)及不确定度 merged = pd.merge(s_avg, b_avg, on='x', how='outer').fillna(0) net_signal = unp.uarray(merged['s_avg'], merged['s_avg_err']) - unp.uarray(merged['b_avg'], merged['b_avg_err']) merged['net_y'] = unp.nominal_values(net_signal) merged['net_y_err'] = unp.std_devs(net_signal) return merged
3. 多DataFrame合并函数
将所有区域处理后的结果按x再次加权平均,得到最终单条曲线:
def combine_all_dfs(df_list): combined = pd.concat(df_list, ignore_index=True) def combine_group(group): net_with_err = unp.uarray(group['net_y'], group['net_y_err']) weights = 1 / (group['net_y_err'] ** 2) final_avg = np.sum(net_with_err * weights) / np.sum(weights) return pd.Series({ 'final_net_y': unp.nominal_values(final_avg), 'final_net_y_err': unp.std_devs(final_avg) }) final_curve = combined.groupby('x').apply(combine_group).reset_index() return final_curve
4. 示例运行
# 构造示例数据(补充误差列) cols = ['x', 's', 'b', 's_err', 'b_err'] A = pd.DataFrame(np.array([[1, 2, 3, 0.1, 0.2], [4, 5, 0, 0.1, 0.2], [6, 7, 0, 0.1, 0.2], [1, 1, 0, 0.1, 0.2], [2, 2, 0, 0.1, 0.2]]), columns=cols) B = pd.DataFrame(np.array([[1, 2, 3, 0.1, 0.2], [4, 0, 5, 0.1, 0.2], [6, 0, 7, 0.1, 0.2], [1, 0, 1, 0.1, 0.2], [2, 0, 2, 0.1, 0.2]]), columns=cols) # 处理单个DataFrame processed_A = process_single_df(A) processed_B = process_single_df(B) # 合并得到最终曲线 final_curve = combine_all_dfs([processed_A, processed_B]) print(final_curve)
关键说明
- 零值过滤:通过布尔索引(
df[col] != 0)实现,本质是利用numpy掩码功能提取有效数据,确保缺失值不参与计算。 - 不确定度传递:
uncertainties.unumpy自动处理加减、加权平均的误差传递,无需手动推导公式。 - 合并逻辑:先在单区域内合并多列数据,再跨区域合并同一
x的结果,保证最终曲线的一致性。
内容的提问来源于stack exchange,提问作者ARGratrex
相关产品推荐
相关产品推荐

