使用AWK逐列比较连续行并按规则赋值的技术求助
使用AWK对比基因型列的相邻行数据(忽略顺序)
没问题,我帮你实现一个符合需求的AWK脚本,先理清楚核心思路:我们需要先统一基因型的格式(消除顺序差异,比如把-/+转为+/-),然后自定义对比规则,最后逐行完成相邻行的对比并输出结果。
步骤拆解
- 基因型标准化:写一个辅助函数,把基因型的两个组分按固定顺序排列,确保不同写法的同一基因型能被识别为相同项。
- 对比规则定义:用数组存储不同基因型组合对应的输出数值,你可以根据自己的需求随时修改。
- 逐行数据处理:保存上一行的基因型数据,和当前行完成对比后输出结果。
输入文件示例(假设文件名为genotypes.txt)
id sample1 sample2 sample3 6 +/+ +/+ +/- 16 -/- +/+ +/+ 20 +/- +/+ +/+ 21 +/- +/+ +/+ 22 +/+ +/+ -/- 25 +/+ +/+ +/+
AWK脚本实现
创建一个名为compare_genotypes.awk的文件,内容如下:
# 标准化基因型:消除顺序影响,比如将-/+转为+/- function normalize_gt(gt) { split(gt, arr, "/") if (arr[1] > arr[2]) { temp = arr[1] arr[1] = arr[2] arr[2] = temp } return arr[1] "/" arr[2] } BEGIN { # 定义对比规则:修改这里的数值即可自定义输出结果 # 格式:comp["基因型A->基因型B"] = 对应输出值 comp["+/+->+/+"] = 1 comp["+/+->+/-"] = 0 comp["+/+->-/-"] = 0 comp["+/-->+/+"] = 0 comp["+/-->+/-"] = 1 comp["+/-->-/-"] = 0 comp["-/-->+/+"] = 0 comp["-/-->+/-"] = 0 comp["-/-->-/-"] = 1 } # 处理表头,生成结果文件的表头 NR == 1 { printf "id_pair" for (i=2; i<=NF; i++) { printf " %s_comp", $i } printf "\n" next } # 处理数据行,完成相邻行对比 NR > 1 { # 标准化当前行的所有基因型 for (i=2; i<=NF; i++) { curr_gt[i] = normalize_gt($i) } # 从第二行数据开始,和上一行对比输出 if (NR > 2) { printf "%d-%d", prev_id, $1 for (i=2; i<=NF; i++) { # 生成对比键,查找对应输出数值 key = prev_gt[i] "->" curr_gt[i] printf " %d", comp[key] } printf "\n" } # 更新上一行的ID和基因型,供下一轮对比使用 prev_id = $1 for (i=2; i<=NF; i++) { prev_gt[i] = curr_gt[i] } }
运行脚本
在终端执行以下命令:
awk -f compare_genotypes.awk genotypes.txt
输出结果
id_pair sample1_comp sample2_comp sample3_comp 6-16 0 1 0 16-20 0 1 1 20-21 1 1 1 21-22 0 1 0 22-25 1 1 0
自定义修改说明
- 调整对比规则:直接修改
BEGIN块里的comp数组即可,比如如果需要+/+和+/-对比输出0.5,就把comp["+/+->+/-"] = 0.5。 - 适配其他基因型格式:如果你的基因型是
0/1、1/1这类数字格式,只需要修改normalize_gt函数里的排序逻辑(比如按数字大小排序)。
内容的提问来源于stack exchange,提问作者user3438524
相关产品推荐
相关产品推荐

