【问题标题】:Duplicate removal based on two fields while keeping the lowest value in the third field基于两个字段的重复删除,同时在第三个字段中保留最小值
【发布时间】:2015-02-08 09:57:45
【问题描述】:

我想删除包含三列的 txt 文件中的重复项。重复项是具有相同“id”和“descr”的那个,我只需要保留最低值。

id1 descr1  0.9
id1 descr1  1.23
id1 descr1  0.3
id1 descr2  0.5
id2 descr2  23.1
id3 descr3  1.2
id3 descr3  14.3
id3 descr3  0.5
id3 descr3  0.34
id3 descr4  4.5

所以,我想收到以下内容

id1 descr1  0.3
id1 descr2  0.5
id2 descr2  23.1
id3 descr3  0.34
id3 descr4  4.5

现在,我有以下技巧

sort -k1,1 -k2,2 -k3,3n file.txt

以及如何取field1+field2的第一次出现?

【问题讨论】:

    标签: text awk duplicates


    【解决方案1】:
    sort -k 3 < File | awk '!a[$1" "$2]++'
    

    示例:

    sdlcb@Goofy-Gen:~/AMD$ cat File
    id1 descr1  0.9
    id1 descr1  1.23
    id1 descr1  0.3
    id1 descr2  0.5
    id2 descr2  23.1
    id3 descr3  1.2
    id3 descr3  14.3
    id3 descr3  0.5
    id3 descr3  0.34
    id3 descr4  4.5
    sdlcb@Goofy-Gen:~/AMD$ sort -k 3 < File | awk '!a[$1" "$2]++'
    id1 descr1  0.3
    id3 descr3  0.34
    id1 descr2  0.5
    id2 descr2  23.1
    id3 descr4  4.5
    

    虽然这与您的预期输出不完全匹配,但我希望这对您来说已经足够了。

    首先我们根据第三个字段进行排序,输出如下:

    id1 descr1  0.3
    id3 descr3  0.34
    id1 descr2  0.5
    id3 descr3  0.5
    id1 descr1  0.9
    id3 descr3  1.2
    id1 descr1  1.23
    id3 descr3  14.3
    id2 descr2  23.1
    id3 descr4  4.5
    

    现在我们正在删除包含相同first and second 字段的行。为此,我们使用数组a,索引为$1space$2。由于我们第一次递增a[$1" "$2],下一次出现的相同first and second 字段将被忽略,因为a[$1" "$2] 不会为0,因此!a[$1" "$2] 将为false。

    【讨论】:

    • 您应该在$1$2 之间添加一些空格或分隔符。如果不是,我已经看到它失败(取决于输入数据)。有些喜欢awk '!a[$1FS$2]++'awk '!a[$1" "$2]++'
    • 你能解释一下'!a[$1$2]++'部分吗?
    • @JohnAmraph '!x[$0]++' 是一种删除awk 中重复行的方法。在 Google 上搜索 awk remove duplicate,你会发现一些关于它是如何工作的解释。
    【解决方案2】:

    你喜欢这样的:

    awk '{s=$1 FS $2;a[s]=a[s]<$3&&a[s]?a[s]:$3} END { for (i in a) print i,a[i]}' file
    id1 descr1 0.3
    id2 descr2 23.1
    id1 descr2 0.5
    id3 descr3 0.34
    id3 descr4 4.5
    

    或某种:

    awk '{s=$1 FS $2;a[s]=a[s]<$3&&a[s]?a[s]:$3} END { for (i in a) print i,a[i]}' file | sort
    id1 descr1 0.3
    id1 descr2 0.5
    id2 descr2 23.1
    id3 descr3 0.34
    id3 descr4 4.5
    

    【讨论】:

    • 可能想要将&amp;&amp;a[s] 更改为&amp;&amp;(a in s),因为它可以为零且不更新:)
    • @Jidder 我以前从未见过这种方式,(a in s) 给出了这个错误:awk: cmd. line:1: (FILENAME=t FNR=1) fatal: attempt to use array 'a' in a scalar context
    • 意思是(s in a)对不起!
    • @Jidder 如果我确实使用了(s in a),我不会得到任何数据输出。
    • 试试(s in a)&amp;&amp;a[s]&lt;$3而不是a[s]&lt;$3&amp;&amp;(s in a)
    【解决方案3】:

    仅使用排序:

    ~$ sort -t' ' -k4n myfile|sort -k1,2 -t' ' -u
    

    首先,使用第 4 个字段进行数字排序(使用空格作为分隔符,数字是第 4 个字段,因为它们之前有 2 个连续的空格):

    ~$ sort -t' ' -k4n myfile
    id1 descr1  0.3
    id1 descr1  0.9
    id1 descr2  0.5
    id3 descr3  0.34
    id3 descr3  0.5
    id1 descr1  1.23
    id3 descr3  1.2
    id3 descr4  4.5
    id3 descr3  14.3
    id2 descr2  23.1
    

    然后使用-u 删除第一个和第二个字段的重复行:

    ~$ sort -t' ' -k4n myfile|sort -k1,2 -t' ' -u
    id1 descr1  0.3
    id1 descr2  0.5
    id2 descr2  23.1
    id3 descr3  0.34
    id3 descr4  4.5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 2019-01-31
      • 1970-01-01
      • 2021-08-27
      相关资源
      最近更新 更多