Linux
用唯一標識符替換所有列中的每個唯一值
我有一個包含 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
誰能為此提出一個優雅的解決方案?任何幫助將不勝感激。
這是一個非常簡單的方法。對我來說很好,使用 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" }
$ 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" } }
它首先為字元串分配
NA
ID 1(在輸出之前,ID 始終減 1)並將計數器更新n
為 1。n
將始終是分配給前一個字元串的 ID。對於每個輸入行,我們遍歷欄位。如果沒有為目前欄位中的字元串分配 ID,我們分配一個並修改該欄位。
然後列印該行及其修改的欄位。
最後,所有字元串及其對應的 ID 都儲存在名為
map
.對於給定的輸入,這個文件可能看起來像
bb 2 ee 7 cc 3 NA 0 tt 8 dd 5 yy 4 aa 1 uu 6