
本文介绍使用python对文本文件中具有相同前缀标识(如apple_1、apple_2)的连续行进行数值列聚合,按“_1”作为新组起始标志,自动计算每组内各数值列的算术平均值。
在处理结构化但非标准格式的日志或实验数据时,常遇到类似场景:多行记录共享同一逻辑实体名(如 apple_1, apple_2, apple_3),需将这些“相邻且同源”的行合并为一行统计结果——典型操作即计算各数值列的平均值。关键在于识别分组边界:本例中,以 _1 结尾的行(如 apple_1, book_1)标志着一个新组的开始,而其后连续出现的 _2, _3 等则属于该组,直到下一个 _1 出现为止。
以下是一个轻量、无外部依赖的纯 Python 实现:
def averages(lst, n):
"""生成器:对列表中每个元素除以 n,返回浮点平均值"""
for v in lst:
yield v / n
def dump(prev, cols, count):
"""输出当前组的聚合结果:前缀 + 各列平均值"""
if prev: # 避免首组前的空输出
print(prev, *averages(cols, count))
# 主逻辑
with open("example.txt") as data:
cols = [] # 存储当前组所有行对应列的累加和
count = 0 # 当前组行数计数器
prev = None # 当前组的公共前缀(如 'apple')
for line in data:
parts = line.split()
if not parts: # 跳过空行
continue
key, *values = parts
nums = list(map(float, values)) # 转为浮点数,支持小数输入
# 拆分键名:'apple_1' → ('apple', '1')
fruit, suffix = key.rsplit("_", 1)
if suffix == "1":
# 遇到新组起点:先输出上一组结果(若存在)
dump(prev, cols, count)
# 重置为新组
prev = fruit
cols = nums.copy() # 初始化累加数组
count = 1
else:
# 同组后续行:逐列累加
for i, val in enumerate(nums):
cols[i] += val
count += 1
# 文件结束,输出最后一组
dump(prev, cols, count)运行效果(输入示例文件):
apple 2.0 3.0 4.0 book 1.0 4.0 5.0 cook 3.0 5.0 6.0 book 2.0 3.0 4.0
✅ 注意事项:
- 该算法严格依赖 _1 作为分组锚点,不依赖全局去重或字典索引,因此天然保持原始行序与分组顺序;
- 所有数值列均强制转为 float,确保精度并兼容小数输入;
- 若某组仅含一行(如独立的 book_1),其输出即为原值(等价于除以 1);
- 空行会被自动跳过,增强鲁棒性;
- 如需整数输出,可在 print() 中对 *averages(...) 结果做 int(round(x)) 处理,但建议保留浮点以避免精度损失。
此方案简洁、高效、可读性强,适用于中等规模数据(百万行内),无需加载全部数据到内存,适合流式处理场景。









