根据 id 对和较高较低值解析文件

根据 id 对和较高较低值解析文件

File1 有 8 列。第 3 列和第 4 列形成一对,如 rs|860 rs|756,与该对关联的值位于第 8 列。

bb  yy  rs|860  rs|756  xx  aa  0.7 2234
bb  yy  rs|310  rs|260  xx  aa  0.3 9838
bb  yy  rs|110  rs|77   xx  aa  0.5 2291
bb  yy  rs|756  rs|860  xx  aa  0.4 2269
bb  yy  rs|110  rs|77   xx  aa  0.9 1112
bb  yy  rs|756  rs|860  xx  aa  0.8 3269
bb  yy  rs|233  rs|79   xx  aa  0.4 1397
bb  yy  rs|79   rs|233  xx  aa  0.7 1397

列 3 和 4 或 4 和 3 的对应该被相同地对待,例如 rs|860 rs|756 == rs|756 rs|860。接下来,第一行中的对也可能出现在第 4 行和第 6 行中(相反)。简单地说,AB = BA = BA。首先,我想按行对 col3 和 col4 进行排序,这可以使数据像 AB = AB = AB 一样。接下来,在所有出现的对中,只有一个应该在第 8 列保留最大值。例如,rs|860 rs|756 在第 6 行处具有最大值(即 3269),因此应删除第 1 行和第 4 行。同样,在 rs|110 的情况下,应删除 rs|77 row5。接下来,如果在第 8 列有相似值的对,则应保留在第 7 列具有较高值的​​对。例如,如果是 rs|233 rs|79 row7,则应删除第 7 列值较低的值 (0.4)。对于任意一对,如果第 8 列和第 7 列都没有较高/较低差异,则可以删除任何一个。

所需的输出 File2

bb  yy  rs|260  rs|310  xx  aa  0.3 9838
bb  yy  rs|77   rs|110  xx  aa  0.5 2291
bb  yy  rs|756  rs|860  xx  aa  0.8 3269
bb  yy  rs|79   rs|233  xx  aa  0.7 1397

答案1

这是一个不优雅的awk解决方案:

{
    split($3, a, "|")
    split($4, b, "|")
    if (a[2] > b[2]){
        $3=b[1]"|"b[2]
        $4=a[1]"|"a[2]
    }
    split(arr[$3" "$4], c, " ")
    if ($8 > c[8]){
        arr[$3" "$4] = $0
    }
}
END{
    for (item in arr){
        print(arr[item])
    }
}

运行与

awk -f script.awk input

它不保留间距,并且顺序是随机的。

答案2

建立在pfnuesel 的回答,

{
    split($3, a, "|")
    split($4, b, "|")
    if (a[2] > b[2]){
        $3=b[1]"|"b[2]
        $4=a[1]"|"a[2]
    }
    key=$3" "$4
    split(arr[key], c, " ")
    if ($8 > c[8]  ||  ($8 == c[8] && $7 > c[7])){
        arr[key] = $0
    }
}
END{
    for (item in arr){
        print(arr[item])
    }
}

如问题中所示(但未明确说明),这假设第三列和第四列中的值的形式为

一些_字符串|数字

其中空格仅供说明之用,并且细绳不包含任何|字符。这些标记将根据数字s;这细绳不比较前缀。

如在pfnuesel 的回答,用法是

awk -f script.awk file1

输入文件的确切间距丢失,但可以通过管道通过(重新)创建可读的列间距 column -t;例如,

awk -f script.awk file1 | column -t > file2

相关内容