
本文介绍一种基于pandas的高效方法,通过pd.concat()横向合并多个同索引(日期)dataframe,再利用apply()与value_counts(normalize=true)逐行统计“yes/no”占比,避免嵌套循环,显著提升可读性与执行效率。
本文介绍一种基于pandas的高效方法,通过pd.concat()横向合并多个同索引(日期)dataframe,再利用apply()与value_counts(normalize=true)逐行统计“yes/no”占比,避免嵌套循环,显著提升可读性与执行效率。
在处理多源时序分类数据(如50个含日期索引、单列“Yes/No”标签的DataFrame)时,手动遍历每个日期和每个DataFrame不仅代码冗长,还易出错且性能低下。推荐采用向量化聚合 + 行级统计的范式,核心步骤如下:
1. 横向拼接所有DataFrame
使用 pd.concat(..., axis=1) 将所有DataFrame按列合并,自动对齐相同日期索引。即使部分DataFrame日期不完全一致,pandas也会以并集为新索引,缺失位置填充 NaN(后续会妥善处理):
import pandas as pd # 示例:3个DataFrame(实际中可替换为包含50个df的列表) dfs = [test1, test2, test3] # 假设已定义 combined = pd.concat(dfs, axis=1)
✅ 优势:无需预检查索引一致性;自动对齐日期;内存友好(不复制原始数据)。
2. 按行统计“Yes/No”占比
对合并后的DataFrame逐行应用 value_counts(normalize=True),直接获得该日期下所有DataFrame中“Yes”和“No”的比例:
# 统计每行(即每个日期)的Yes/No占比,自动忽略NaN
results = combined.apply(
lambda row: row.value_counts(normalize=True),
axis=1
).fillna(0) # 将未出现的类别(如某日无"No")补0,确保列完整
# 可选:保留4位小数提升可读性
results = results.round(4)
输出结果是一个MultiIndex DataFrame(行索引为日期,列名为“Yes”“No”),例如:
yes no 2024-01-01 1.0 0.0 2024-01-01 0.6 0.4 ...
3. 进阶技巧与注意事项
- 获取频次而非占比:移除 normalize=True 参数,value_counts() 返回绝对计数;
- 统一列名:若需区分来源,可在拼接后重命名列(如 combined.columns = [f'df_{i}' for i in range(len(dfs))]);
- 缺失值鲁棒性:value_counts(..., dropna=False) 可显式包含 NaN 计数(本例中通常不需);
- 性能提示:对50+ DataFrame,建议先验证索引是否已排序(combined.index.is_monotonic_increasing),避免隐式排序开销。
该方法将原本O(N×M)复杂度的嵌套循环简化为O(N+M)级别的向量化操作,代码简洁、逻辑清晰,且天然支持任意数量的输入DataFrame——是处理同类聚合任务的标准实践。











