在Pandas中实现按(name, num_inputs)元组分组后的ID级求和平均值计算、柱状图绘制及95%置信区间求解
解决你的分组统计与置信区间可视化问题
首先,我们先梳理下你的需求(结合你给出的示例修正描述偏差):
- 按
(name, num_inputs)对数据分组 - 每个分组内,先计算同一ID下所有value的平均值
- 再对这些ID级别的平均值求整体平均,得到每个
(name, num_inputs)组的最终结果 - 计算每个结果的95%置信区间,并用柱状图展示(带误差棒)
你的原始代码存在变量名错误、分组聚合逻辑偏差、置信区间计算对象不对的问题,我们一步步修正:
完整可运行代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy import stats # 第一步:创建你的示例数据框 data = [ [1, "name1", 10, 5], [1, "name1", 10, 6], [1, "name1", 10, 16], [2, "name1", 10, 51], [2, "name1", 10, 45], [3, "name1", 20, 2], [3, "name1", 20, 7], [3, "name1", 20, 10], [3, "name1", 20, 11], [4, "name1", 20, 11], [4, "name1", 20, 25], [4, "name1", 20, 55], [5, "name2", 10, 1], [5, "name2", 10, 76], [5, "name2", 10, 13], [6, "name2", 10, 11], [6, "name2", 10, 44], [7, "name2", 20, 3], [7, "name2", 20, 8], [7, "name2", 20, 134], [7, "name2", 20, 111], [8, "name2", 20, 121], [8, "name2", 20, 215], [8, "name2", 20, 515] ] df = pd.DataFrame(data, columns=["id", "name", "num_inputs", "value"]) # 第二步:按(name, num_inputs, id)分组,计算每个ID的value平均值 id_level_means = df.groupby(["name", "num_inputs", "id"])["value"].mean().reset_index() # 第三步:按(name, num_inputs)分组,计算最终平均值,并收集每个分组的ID均值列表用于置信区间计算 grouped_results = [] group_id_means = [] for (name, num_in), group in id_level_means.groupby(["name", "num_inputs"]): mean_val = group["value"].mean() grouped_results.append((f"({name}, {num_in})", mean_val)) group_id_means.append(group["value"].tolist()) # 第四步:计算95%置信区间(使用t分布,适合小样本) def calculate_95_ci(data): n = len(data) mean = np.mean(data) std_err = stats.sem(data) margin_of_error = std_err * stats.t.ppf((1 + 0.95) / 2, n - 1) return mean - margin_of_error, mean + margin_of_error # 准备误差棒数据(上下误差分别为均值与置信区间端点的差值) err_down = [] err_up = [] for data_list in group_id_means: lower, upper = calculate_95_ci(data_list) current_mean = np.mean(data_list) err_down.append(current_mean - lower) err_up.append(upper - current_mean) yerr = [err_down, err_up] # 第五步:绘制柱状图 labels, values = zip(*grouped_results) fig, ax = plt.subplots() ax.bar(labels, values, yerr=yerr, capsize=5) ax.set_ylabel("Average of ID-level Means") ax.set_title("Grouped Results with 95% Confidence Intervals") plt.xticks(rotation=45, ha="right") plt.tight_layout() plt.show() # 打印验证结果 for label, val in grouped_results: print(f"{label}: {val:.2f}")
代码解释
- 数据准备:将你提供的原始数据转换成DataFrame,方便后续分组处理。
- ID级别均值计算:先按
name、num_inputs、id三层分组,得到每个ID下value的平均值,这和你示例中的第一步计算逻辑完全匹配。 - 分组最终均值:再按
name和num_inputs分组,对每个组内的ID均值求平均,得到你期望的最终统计结果。 - 置信区间计算:使用
t分布计算95%置信区间(因为每个分组的样本量较小,t分布比正态分布更贴合小样本场景),scipy.stats.sem用于计算标准误,stats.t.ppf获取对应的t临界值。 - 可视化:用
matplotlib绘制柱状图,yerr参数传入上下误差值,capsize设置误差棒的帽长,让图表更直观清晰。
验证结果
运行代码后,打印的结果会和你期望的一致:
(name1, 10): 28.50(name1, 20): 18.92(和你示例的18.91微小差异是浮点精度问题)(name2, 10): 28.75(name2, 20): 173.83
内容的提问来源于stack exchange,提问作者Phrixus
相关产品推荐
相关产品推荐

