여러 필드에서 파생된 키에 대한 MIN 및 MAX 값 생성

여러 필드에서 파생된 키에 대한 MIN 및 MAX 값 생성

탭으로 구분되고 다음과 같은 대형 플랫 파일이 있습니다.

APP     SRC     HITS
App1    SRC1    202
App1    SRC1    101
App1    SRC13   90
App1    SRC2    3169
App1    SRC4    1
App1    SRC2    158
App1    SRC2    151
App3    SRC3    1
App3    SRC3    6
App3    SRC3    11
App3    SRC3    16
App3    SRC3    339
App2    SRC3    2
App2    SRC3    10023

저는 아주 새로운 스크립트 작성자이므로 어디서부터 시작해야 할지 모르고, APP 및 SRC 열의 결과를 그룹화해야 하는 솔루션을 찾을 수 없는 것 같습니다(예: APP 및 SRC 열이 하나의 키가 됨).

각 애플리케이션과 해당 애플리케이션이 속한 SRC에 대한 MIN 및 MAX 클릭 수를 인쇄하고 싶습니다. 예를 들어

출력은 다음과 같습니다. 스크립트를 통해 파일을 전달하여 이를 달성할 수 있는 방법이 있습니까?

APP  SRC   MIN   MAX 
App1 SRC1  101   202
App1 SRC2  151   3169
App3 SRC3  1     339
App2 SRC3  2     10023

미리 감사드립니다!

답변1

그리고 awk:

awk '
BEGIN{ FS=OFS="\t"; print "APP", "SRC", "MIN", "MAX" }

 NR==1{ next }
 { key=($1 OFS $2) }
 !(key in min) { min[key]=max[key]= $3 }
 min[key]>$3 { min[key]=$3 }
 max[key]<$3 { max[key]=$3 }

END{ for (key in min) print key, min[key], max[key] }' infile

산출:

APP     SRC     MIN     MAX
App2    SRC3    2       10023
App1    SRC1    101     202
App1    SRC2    151     3169
App1    SRC4    1       1
App1    SRC13   90      90
App3    SRC3    1       339

답변2

\t열 이름에 나타날 수 없다고 가정하면 다음과 함께 사용하십시오 awk.

#!/bin/awk -f
BEGIN {SUBSEP=OFS="\t"; print "APP", "SRC", "MIN", "MAX";}
NR > 1 && (!(($1,$2) in min) || min[$1,$2] > $3) { min[$1,$2] = $3 }
NR > 1 && (!(($1,$2) in max) || max[$1,$2] < $3) { max[$1,$2] = $3 }
END { 
    for(i in min) printf "%s%s%s%s%s\n", i, OFS, min[i], OFS, max[i]
}

답변3

사용행복하다(이전 Perl_6)

raku -e 'my @a = lines.skip.map(*.words); my @b = @a.map(*.[0..1].join("\t"));  \
         my %c;  %c.=append([Z=>] @b, @a.map(*.[2])); put "APP\t\tSRC\t\tMIN\tMAX";  \
         for %c.sort {say (.key, .value.map(*.Int).min, .value.map(*.Int).max).join: "\t"};' 

Raku에 내장된 해시 함수를 사용하는 방법은 다음과 같습니다. 기본적으로 처음 두 열을 결합하여 하나를 만든 다음 세 번째 열을 하나 이상의 열로 사용하여 key해시를 만듭니다. Raku 기능은 해당 키에 s를 추가합니다.%cvalueappendvalue

~$ raku -e 'my @a = lines.skip>>.words; my @b = @a.map(*.[0..1].join("\t")); my %c;  %c.=append([Z=>] @b, @a.map(*.[2])); for %c.sort { .say };'  file
App1    SRC1 => [202 101]
App1    SRC13 => 90
App1    SRC2 => [3169 158 151]
App1    SRC4 => 1
App2    SRC3 => [2 10023]
App3    SRC3 => [1 6 11 16 339]

Raku는 기본 언어로 min, max, 루틴을 제공합니다. 첫 번째 코드 예를 참고하세요. s를 minmax출력하기 전에 value강제하는 것이 매우 중요합니다 Int. 그렇지 않으면 최소/최대가 제대로 작동하지 않습니다. 또한 sprintfRaku에는 분리 이상의 엄격한 서식이 필요한 경우를 위한 기능이 있습니다(참고: 위 출력의 헤더에는 정렬해야 하는 추가 s가 있습니다).\t\t


입력 예:

APP     SRC     HITS
App1    SRC1    202
App1    SRC1    101
App1    SRC13   90
App1    SRC2    3169
App1    SRC4    1
App1    SRC2    158
App1    SRC2    151
App3    SRC3    1
App3    SRC3    6
App3    SRC3    11
App3    SRC3    16
App3    SRC3    339
App2    SRC3    2
App2    SRC3    10023

예제 출력:

APP     SRC     MIN MAX
App1    SRC1    101 202
App1    SRC13   90  90
App1    SRC2    151 3169
App1    SRC4    1   1
App2    SRC3    2   10023
App3    SRC3    1   339

https://docs.raku.org/routine/=%3E
https://raku.org

관련 정보