각 열의 백분율을 계산하는 방법은 무엇입니까?

각 열의 백분율을 계산하는 방법은 무엇입니까?

일부 데이터를 각 열에 대한 합계의 백분율로 변환하려고 합니다. 각 열에 대해 이 작업을 수행해야 한다는 점을 제외하면 이 스레드와 매우 유사합니다. AWK를 사용하여 합계 계산 및 나누기

데이터는 다음과 같을 것입니다(그러나 더 많은 열과 행).

ID     Sample1     Sample2      Sample3
One      10          0            5
Two      3           6            8
Three    3           4            7

원하는 출력은 다음과 같습니다.

ID     Sample1     Sample2     Sample3
One     62.50        0.0        25.0
Two     18.75       60.0        40.0
Three   18.75       40.0        35.0   

다음은 단일 열에 대해 작동하지만 첫 번째 열을 제외한 모든 열에 대해 이 작업을 수행하고 싶습니다.

gawk -F"\t" '{a[NR]=$1;x+=(b[NR]=$2)}END{while(++i<=NR)print a[i]"\t"100*b[i]/x}' file.txt 

귀하가 제공할 수 있는 도움에 진심으로 감사드립니다.

답변1

출력은 요청한 것과 100% 동일하지는 않지만 충분히 비슷할 것으로 예상됩니다.

function percent(value, total) {
    return sprintf("%.2f", 100 * value / total);
}
{
    label[NR] = $1
    for (i = 2; i <= NF; ++i) {
        sum[i] += col[i][NR] = $i
    }
}
END {
    title = label[1]
    for (i = 2; i <= length(col) + 1; ++i) {
        title = title "\t" col[i][1];
    }
    print title
    for (j = 2; j <= NR; ++j) {
        line = label[j]
        for (i = 2; i <= length(col) + 1; ++i) {
            line = line "\t" percent(col[i][j], sum[i]);
        }
        print line
    }
}

출력을 생성합니다.

ID    Sample1 Sample2 Sample3
One   62.50   0.00    25.00
Two   18.75   60.00   40.00
Three 18.75   40.00   35.00

실행해gawk -f script.awk file.txt

물론이죠할 수 있다스크립트를 한 줄로 단순화하되, 읽고 유지하기 쉽도록 이와 같은 스크립트 파일에 보관하는 것이 더 낫다고 생각합니다.

GNU AWK뿐만 아니라 BSD AWK에서도 작동하는 더 간단하고 더 나은 버전:

function percent(value, total) {
    return sprintf("%.2f", 100 * value / total)
}
BEGIN { OFS = "\t" }
NR == 1 { gsub(/ +/, OFS); print; next }
{
    label[NR] = $1
    for (i = 2; i <= NF; ++i) {
        sum[i] += col[i, NR] = $i
    }
}
END {
    for (j = 2; j <= NR; ++j) {
        $1 = label[j]
        for (i = 2; i <= NF; ++i) {
            $i = percent(col[i, j], sum[i])
        }
        print
    }
}

관련 정보