如何从结构化压缩文件中高效随机抽取n组有序行
嘿,针对你要从压缩的4行分组文件里高效随机抽取半数组的需求,我给你整理了几个实用方案——优先用Unix工具链(毕竟bash处理这类文本任务效率拉满),也优化了你原本的Python思路~
方案一:用Unix工具链高效处理(无需全解压到磁盘)
这个方案全程用管道处理,不用把整个大文件解压到磁盘,能极大节省IO开销,适合处理超大文件:
步骤说明
- 先统计总组数,计算需要抽取的半数数量
- 给每个分组标记唯一ID,随机筛选半数ID
- 根据选中的ID提取对应分组
完整命令
# 1. 统计总组数并计算抽取数量 total_groups=$(zcat origin.txt.gz | awk '/^@/{count++} END{print count}') sample_size=$((total_groups / 2)) # 2. 生成随机选中的组ID列表(临时文件暂存) zcat origin.txt.gz | awk '/^@/{group_id++} {print group_id "\t" $0}' | cut -f1 | uniq | shuf -n $sample_size > selected_groups.txt # 3. 根据选中的ID提取对应分组 zcat origin.txt.gz | awk -v ids="$(cat selected_groups.txt)" ' BEGIN { split(ids, id_arr, "\n"); for (i in id_arr) selected[id_arr[i]] = 1; } /^@/{current_group++} selected[current_group] {print $0} ' > /home/labs/amit/diklag/subset.txt # 清理临时文件 rm selected_groups.txt
优点
- 全程流式处理,不用占用大量磁盘空间存储全量解压文件
- 依赖
zcat/awk/shuf等系统自带工具,不用额外安装依赖
方案二:优化后的Python实现(无需提前解压文件)
如果你更倾向用Python处理,我优化了你的思路——不用调用subprocess解压到文件,直接用Python内置的gzip模块读取压缩文件,减少中间步骤:
import gzip import random from itertools import zip_longest # 辅助函数:按固定行数分组 def grouper(iterable, n, fillvalue=None): args = [iter(iterable)] * n return zip_longest(*args, fillvalue=fillvalue) path = "origin.txt.gz" new_path = "/home/labs/amit/diklag/subset.txt" # 读取所有有效分组(过滤掉不符合@开头的无效组) groups = [] with gzip.open(path, 'rt', encoding='utf-8') as f: for group in grouper(f, 4): # 确保组的第一行以@开头,且组内行不为空 if group[0] and group[0].startswith('@'): groups.append(''.join(line for line in group if line)) # 随机抽取半数分组 sample_size = len(groups) // 2 selected_groups = random.sample(groups, sample_size) # 写入结果文件 with open(new_path, 'w', encoding='utf-8') as f: f.writelines(selected_groups)
优点
- 纯Python处理,不用依赖外部命令,逻辑更可控
- 直接读取压缩文件,避免磁盘IO浪费
内容的提问来源于stack exchange,提问作者dikla gelbard
相关产品推荐
相关产品推荐

