【问题标题】:Remove duplicates and keep line which contains max value from one column - LINUX删除重复项并保留一列中包含最大值的行 - LINUX
【发布时间】:2017-08-06 18:50:23
【问题描述】:

大家!

我想删除重复项,并在具有 4 个字段的文件中保留一列(第 4 列)中具有最高值的行。我必须在 Linux 服务器中执行此操作。

之前

gene  subj  e-value ident
  g1    h1    0.05   75.5
  g1    h2    0.03   60.6 
  g2    h7    0.00   80.5
  g2    h9    0.00   50.3
  g2    h4    0.03   90.7
  g3    h5    0.10   30.5
  g3    h8    0.00   76.8
  g4    h11   0.00   80.7

之后

gene  subj  e-value ident
  g1    h1    0.05   75.5
  g2    h4    0.03   90.7
  g3    h8    0.00   76.8
  g4    h11   0.00   80.7

非常感谢,如果我重复了一些问题,我很抱歉!但我没有找到我的问题的答案。

【问题讨论】:

  • 你试过什么?
  • 我试过基于awk的命令,如cat blast_selected_split0_outfmt6.txt | awk -F'\t' '{if($1$3 in a){if($7>a[$1$3]){a[$1$3]=$7;r[$1$3]=$0;}}else if ($3$1 in a){if($7>a[$3$1]){a[$3$1] = $7;r[$3$1] = $0;}}else{a[$1$3]=$7; r[$1$3]=$0;}} END{for(x in r)print r[x]}'
  • 但它保持重复
  • 非常感谢!!
  • wrt 您发布的 awk 命令 - 不要连接数据来为数组创建索引,因为这不会创建唯一索引。 a bc 的串联 = ab c 的串联 = abc。因此,您应该使用a[$1,$3]($1,$3) in a,而不是使用a[$1$3]$1$3 in a

标签: linux awk duplicates max


【解决方案1】:

你可以试试这个,如果不带header的输出没问题的话:

tail -n +2 file.txt | sort -k1,1 -k4,4rn | sort -uk1,1

解释:

tail -n +2 file.txt

将删除标题,因此它们不会参与所有排序。

sort -k1,1 -k4,4rn

将首先按第 1 列 (-k1,1) 排序,然后按第 4 列按数字倒序排序 (-k4,4rn)

最后:

 sort -uk1,1

将仅考虑第一列删除重复项。

请注意,-k1,1 表示从第一列到第一列,因此-k4,4 是从第 4 列到第 4 列。调整以适合您的列。

【讨论】:

  • 非常感谢!重复项已被删除,但它没有发现第 7 列中的最大值。实际上,我的文件比示例大(它有 7 列),我简化为 4 列文件。所以我使用了这个命令:tail -n +2 file.txt | sort -k1,1 -k4,4rn | sort -uk1,1。有什么问题吗?
  • @M.Sobreiro 更新了我的答案以添加解释,希望对您有所帮助。我想你想要的是tail -n +2 file.txt | sort -k1,1 -k7,7rn | sort -uk1,1
【解决方案2】:

使用 GNU datamash 工具:

datamash --headers -Wfs -g1 max 4 < file | cut -f1-4

输出:

gene  subj  e-value  ident
g1    h1    0.05     75.5
g2    h4    0.03     90.7
g3    h8    0.00     76.8
g4    h11   0.00     80.7

【讨论】:

    【解决方案3】:

    一个 awk 解决方案,但为了简单起见,我喜欢 archimiro 版本。

    awk '
        NR>1 && $1 in arr {
            if ($4 > arr[$1][4]) 
                split($0, arr[$1])
            next
        } 
    
        NR>1 { 
            arr[$1][1] = ""
            split($0, arr[$1]) 
        } 
    
        END { 
            for(i in arr) { 
                for(j in arr[i]) 
                    printf arr[i][j] "\t"
                print ""
            }
        }
    ' data.file
    

    结果:

    g1  h1  0.05    75.5    
    g2  h4  0.03    90.7    
    g3  h8  0.00    76.8    
    g4  h11 0.00    80.7    
    

    【讨论】:

      猜你喜欢
      • 2022-11-15
      • 2021-12-29
      • 2013-07-10
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 2021-09-24
      • 2018-12-29
      相关资源
      最近更新 更多