모든 열의 모든 고유 값을 고유 식별자로 바꿉니다.

모든 열의 모든 고유 값을 고유 식별자로 바꿉니다.

250,000개의 행과 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씩 감소함) 카운터를 n1로 업데이트합니다. 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

GNU awk솔루션(2D 배열 지원 필요)

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

관련 정보