将所有列中的每个唯一值替换为唯一标识符

将所有列中的每个唯一值替换为唯一标识符

我有一个包含 250k 行和 10 列的文件,例如:

img1 aa bb cc ...
img2 aa yy dd ...
img3 uu bb ee ...
img4 NA bb tt ...

我想要一个脚本将该文件转换为:

img1 1 1 1 ...
img2 1 2 2 ...
img3 2 1 3 ...
img4 0 1 4 ...

第一列之后的每一列中的唯一值应替换为从 0 开始的唯一标识符,其中 0 是为字符串“NA”保留的。

另外,对于每一列,我想生成一个包含映射的文件。例如,第二列的文件应为:

NA 0
aa 1
uu 2

谁能为此提出一个优雅的解决方案?任何帮助将不胜感激。

答案1

这是一个非常简单的方法。使用 gawk 3.1.7 对我来说效果很好。

#!/usr/bin/awk -f
{
    for(x=2;x<=NF;x++) {
        if(x$x in a) {
            $x=a[x$x]
        } else {
            if($x=="NA") {
                print $x,0 > "column"x
                a[x$x]=0
                $x="0"
            } else {
                m[x]++
                print $x,m[x] > "column"x
                a[x$x]=m[x]
                $x=m[x]
            }
        }
    }
    print $0 > "results"
}

答案2

$ awk 'BEGIN { id["NA"] = ++n } { for (i=2; i<=NF; ++i) { id[$i] || id[$i] = ++n; $i = id[$i] - 1 } } { print } END { for (i in id) { print i, id[i] - 1 >"map" } }' file
img1 1 2 3
img2 1 4 5
img3 6 2 7
img4 0 2 8

img这会为除第一个列( -column)之外的所有列中的每个值分配一个唯一的 ID 。我选择使 ID 全局唯一,而不是仅对列唯一,因为这会减少必须生成的所需映射文件的数量。

剧本揭晓:

BEGIN   { id["NA"] = ++n }

        {
            for (i=2; i<=NF; ++i) {
                id[$i] || id[$i] = ++n;
                $i = id[$i] - 1
            }
        }

        { print }

END     {
            for (i in id) {
                print i, id[i] - 1 >"map"
            }
        }

它首先为字符串分配NAID 1(输出前 ID 始终减 1),并将计数器更新n为 1。 n将始终是分配给前一个字符串的 ID。

对于每个输入行,我们迭代字段。如果没有为当前字段中的字符串分配 ID,我们会分配一个 ID 并就地修改该字段。

然后打印该行及其修改后的字段。

最后,所有字符串及其对应的 ID 都存储在名为map.

对于给定的输入,该文件可能类似于

bb 2
ee 7
cc 3
NA 0
tt 8
dd 5
yy 4
aa 1
uu 6

答案3

GNUawk解决方案(需要二维数组支持)。

awk '{
    printf "%s ", $1;

    for(i = 2; i <= NF; i++) {
        filename = "column_" i - 1 "_mapping"

        if(NR == 1) {
            arr[i]["NA"] = 0;
            print "NA 0" > filename;    
        }

        if(! ($i in arr[i]) ) {
            cnt[i]++;
            arr[i][$i] = cnt[i];
            print  $i, cnt[i] > filename;   
        }

        printf "%d ", arr[i][$i];
    }

    print "";
}' input.txt

输入

img1 aa bb cc
img2 aa yy dd
img3 uu bb ee
img4 NA bb tt

输出

img1 1 1 1 
img2 1 2 2 
img3 2 1 3 
img4 0 1 4 

映射文件的内容

tail -n +1 -- *_mapping

==> column_1_mapping <==
NA 0
aa 1
uu 2

==> column_2_mapping <==
NA 0
bb 1
yy 2

==> column_3_mapping <==
NA 0
cc 1
dd 2
ee 3
tt 4

相关内容