awk를 사용하여 데이터 피벗

awk를 사용하여 데이터 피벗

awk를 사용하여 파일을 회전하려고 합니다. 다음은 내 입력 파일의 예입니다.

VarName;TimeString;VarValue;Validity;Time_ms
A;23.11.201215:03:53;1;1;41236627696,7593
C;23.11.201215:03:53;2;1;41236627696,7593
D;23.11.201215:03:53;3;1;41236627696,7593
A;23.11.201215:04:53;31;1;41236628391,2037
B;23.11.201215:04:53;12;1;41236628391,2037
C;23.11.201215:04:53;1;1;41236628391,2037
D;23.11.201215:05:53;8;1;41236629097,2222
B;23.11.201215:05:53;7;1;41236629097,2222
C;23.11.201215:05:53;15;1;41236629097,2222

이것이 내가 원하는 결과입니다:

TimeString;Time_ms;A;B;C;D
23.11.201215:03:53;41236627696,7593;1;;2;3
23.11.201215:04:53;41236628391,2037;31;12;1;
23.11.201215:05:53;41236629097,2222;;7;15;8    

이 결과를 얻는 가장 좋은 방법은 무엇입니까?

@steve가 작성한 스크립트를 사용하여 해결되었습니다.

답변1

이것은 사용되는 한 가지 방법입니다 gawk. 다음과 같이 실행합니다:

awk -f script.awk file

콘텐츠 script.awk:

BEGIN {
    FS=OFS=";"
}

NR==1 {
    r = $2 FS $5
    next
}

{
    !x[$1]
    a[$2,$5][$1]=$3
}

END {

    m = asorti(x,y)
    for (k=1;k<=m;k++) {
        r = r FS y[k]
    }
    print r

    n = asorti(a,b)
    for (i=1;i<=n;i++) {
        for (j=1;j<=m;j++) {
            for (k in a[b[i]]) {
                if (k == y[j]) {
                    var = a[b[i]][k]
                }
            }

            line = line FS var
            var = ""
        }
        sub(SUBSEP, FS, b[i])

        print b[i] line
        line = ""
    }
}

또는 라이너는 다음과 같습니다.

awk 'BEGIN { FS=OFS=";" } NR==1 { r = $2 FS $5; next } { !x[$1]; a[$2,$5][$1]=$3 } END { m = asorti(x,y); for (k=1;k<=m;k++) { r = r FS y[k] } print r; n = asorti(a,b); for (i=1;i<=n;i++) { for (j=1;j<=m;j++) { for (k in a[b[i]]) { if (k == y[j]) { var = a[b[i]][k] } } line = line FS var; var = "" } sub(SUBSEP, FS, b[i]); print b[i] line; line = "" } }' file

결과:

TimeString;Time_ms;A;B;C;D
23.11.201215:03:53;41236627696,7593;1;;2;3
23.11.201215:04:53;41236628391,2037;31;12;1;
23.11.201215:05:53;41236629097,2222;;7;15;8


dos2unix먼저 파일을 실행 해야 합니다 . 즉:

dos2unix Flussi0.csv

또는 레코드 구분 기호를 변경하여 Windows 줄 바꿈 끝 모양을 알 수 있습니다 \r\n. 블록에서 이 작업을 수행 awk할 수 있습니다 .BEGIN

BEGIN {
    FS=OFS=";"
    RS="\r\n"
}

입력 파일의 결과는 아래 댓글에 게시됩니다.

"TimeString";"Time_ms";"FIT01";"FIT02";"FIT03";"FIT04";"FIT05";"FIT06"
"22.06.2012 09:31:33";41082396909,7222;1,157408E-02;5,787041E-03;2,507718E-02;2,89352E-03;2,314816E-02;5,787035E-04
"22.06.2012 09:32:34";41082397615,7407;1,157408E-02;5,787041E-03;2,314816E-02;2,89352E-03;2,713479E-02;5,787035E-04
"22.06.2012 09:33:35";41082398321,7593;1,157408E-02;5,787041E-03;2,314816E-02;2,89352E-03;2,314816E-02;5,787035E-04
"22.06.2012 09:34:35";41082399016,2037;1,157408E-02;5,787041E-03;2,314816E-02;2,89352E-03;2,535274E-02;5,787035E-04
"22.06.2012 09:35:36";41082399722,2222;;;;;2,314816E-02;

답변2

가장 좋은 방법은? 나는 모른다. 이것은방법. 나는 코드가 실제로 입력 데이터의 헤더 행을 볼 필요가 없고 단지 TimeString;Time_ms;.

(line > /dev/null; sort) < input_file > tmp0    # Discard the header line; sort the data.
        # Here lies the basic pivot:
awk -F";" '
    {
        print $1 > "tmp1"
        print $2 > "tmp2"
        print $5 > "tmp5"
    }' tmp0
echo "TimeString;Time_ms;\c"
tr "\n" ";" < tmp1; echo
tr "\n" ";" < tmp2; echo
tr "\n" ";" < tmp5; echo

;각 출력 줄은 세미콜론( )으로 끝 납니다 . 당신이 이것을 원하는지 확실하지 않습니다. 원하지 않는 경우 제거할 수 있는 방법을 찾을 수도 있습니다.

답변3

reshape하위 명령 사용밀러( mlr, CSV를 지원하는 도구) 다음을 수행합니다 unsparsify.

$ mlr --csv --fs ';' reshape -s VarName,VarValue then unsparsify file
TimeString;Validity;Time_ms;A;C;D;B
23.11.201215:03:53;1;41236627696,7593;1;2;3;
23.11.201215:04:53;1;41236628391,2037;31;1;;12
23.11.201215:05:53;1;41236629097,2222;;15;8;7

-s하위 명령에 대한 옵션은 reshape키 필드 이름과 값 필드 이름으로 구성된 쉼표로 구분된 쌍을 사용합니다. 그런 다음 긴 너비 피벗 작업을 수행하여 값 필드의 데이터를 사용하여 키 필드에 필드를 만듭니다.

unsparsify일부 필드가 없는 레코드에 빈 필드를 추가해야 하는 작업입니다.

마지막 4개 필드를 올바른 순서로 다시 정렬하고 이 Validity필드를 제거하려면 다음을 수행하십시오.

$ mlr --csv --fs ';' reshape -s VarName,VarValue then unsparsify then reorder -e -f A,B,C,D then cut -x -f Validity file
TimeString;Time_ms;A;B;C;D
23.11.201215:03:53;41236627696,7593;1;;2;3
23.11.201215:04:53;41236628391,2037;31;12;1;
23.11.201215:05:53;41236629097,2222;;7;15;8

또는 더 짧게는 cut하위 명령을 사용하여 출력 필드를 재정렬하고 선택하면 됩니다.

$ mlr --csv --fs ';' reshape -s VarName,VarValue then unsparsify then cut -o -f TimeString,Time_ms,A,B,C,D file
TimeString;Time_ms;A;B;C;D
23.11.201215:03:53;41236627696,7593;1;;2;3
23.11.201215:04:53;41236628391,2037;31;12;1;
23.11.201215:05:53;41236629097,2222;;7;15;8

일반적으로 새로 생성된 필드의 이름을 알 수 없으므로 이름별로 필드를 정렬하고 해당 Validity필드를 제거한 다음 새 필드를 이름별로 언급하지 않고 두 개의 시간 필드를 앞에 배치할 수 있습니다.

$ mlr --csv --fs ';' reshape -s VarName,VarValue then unsparsify then sort-within-records then cut -x -f Validity then reorder -f TimeString,Time_ms file
TimeString;Time_ms;A;B;C;D
23.11.201215:03:53;41236627696,7593;1;;2;3
23.11.201215:04:53;41236628391,2037;31;12;1;
23.11.201215:05:53;41236629097,2222;;7;15;8

관련 정보