代码之家  ›  专栏  ›  技术社区  ›  bapors

比较多行以选择值最小的行

  •  0
  • bapors  · 技术社区  · 5 年前

    column 3> 4 > 5 . 我为第二列对数据集进行了排序,以便将相同的值放在一起。 我的数据集如下所示:

    X1    A 0.38 24.68  2.93
    X2    A 0.38 20.22 14.54
    X3    A 0.38 20.08 00.48
    X3.3  A 0.22 11.55 10.68
    C43   B 0.22 11.55 20.08
    C4.2  C 0.22 11.55  3.08
    C4.5  C 0.22 11.55 31.08
    C42   D 0.96 21.15 11.24
    C44   D 0.22  1.10  1.24
    P1    E 0.42  0.42  0.42
    P2    E 0.42  0.42  0.42
    P3    E 0.42  0.42  0.42
    

    在这里,我想说,如果 second column 与另一行的值相同,然后在 third column 并选择该行中具有最高值的行 第三纵队 .

    second and third columns ,然后我去 forth column 并在此列中比较它们的值,然后获得值最高的行。

    如果行共享 第二列 仍然分享着我们的价值观 third and forth columns fifth column.

    如果 second-third-forth-fifth columns 是相同的(完全重复),然后我打印它们,但添加 'duplicate'

    如果一行没有为任何其他行的第二列共享其值,则没有比较,我保留此列。

    因此,我的预期产出将是:

    X1    A 0.38 24.68  2.93
    C43   B 0.22 11.55 20.08
    C4.5  C 0.22 11.55 31.08
    C42   D 0.96 21.15 11.24
    P1    E 0.42  0.42  0.42duplicate
    P2    E 0.42  0.42  0.42duplicate
    P3    E 0.42  0.42  0.42duplicate
    

    我目前尝试的方法失败了,因为我只能基于第二列进行比较,而不能基于多列条件进行比较,而且我无法保留完整的副本。

    cat data.txt | awk -v OFS="\t" '$1=$1' | sort -k2,2 -k3nr -k4nr -k5nr  | awk '!a[$2]++'
    X1      A       0.38    24.68   2.93
    C43     B       0.22    11.55   20.08
    C4.5    C       0.22    11.55   31.08
    C42     D       0.96    21.15   11.24
    P1      E       0.42    0.42    0.42
    

    我很高兴能学会如何修复它。

    0 回复  |  直到 5 年前
        1
  •  1
  •   tshiono    5 年前

    恐怕下面的代码并不复杂,那么:

    awk -v OFS="\t" '$1=$1' "data.txt" | sort -k2,2 -k3nr -k4nr -k5nr > "tmp.txt"
    
    awk -v OFS="\t" '
        NR==FNR {
            vals = $3","$4","$5
            if (max[$2] == "") max[$2] = vals
            else if (max[$2] == vals) dupe[$2] = 1
            next
        } {
            vals = $3","$4","$5
            if (dupe[$2]) $6 = "duplicate"
            if (max[$2] == vals) print
        }' "tmp.txt" "tmp.txt"
    
    rm -f "tmp.txt"
    
    • 它将排序结果保存在临时文件“tmp.txt”中。
    • awk 脚本通过两个过程处理临时文件。
    • 在第1遍中,它为每个第2列提取“最大值”。
    • 它还检测重复并设置变量 dupe 如果找到的话。
    • 在第二个过程中,它分配变量 $6 一串 duplicate 如果该行具有dupe标志。
    • 然后,它只打印每第二列具有最大值的行。
        2
  •  1
  •   prig9951    5 年前

    这可能不是最优雅的解决方案,但它确实有效

    cat data.txt | awk -v OFS="\t" '$1=$1' | sort -k2,2 -k3nr -k4nr -k5nr  | awk '!a[$2]++' |  cut -f2-  > /tmp/fgrep.$$
    cat data.txt | fgrep -f /tmp/fgrep.$$ | awk '{
      rec[NR] = $0
      idx = sprintf("%s %s %s %s",$2,$3,$4,$5)
      irec[NR] = idx
      dup[idx]++
    }
    END{
      for(i in rec){
        if(dup[irec[i]]> 1){
          print rec[i] "duplicate"
        }else{
          print rec[i]
        }
      }
    }'
    rm /tmp/fgrep.$$
    
    推荐文章