일치하는 필드를 기반으로 열 쌍 합계


11

다음 형식의 큰 파일이 있습니다.

2 1019 0 12 
2 1019 3 0 
2 1021 0 2 
2 1021 2 0 
2 1022 4 5
2 1030 0 1 
2 1030 5 0 
2 1031 4 4

열 2 의 값이 일치하면 두 줄의 열 34 의 값을 합산하고 , 그렇지 않으면 고유 한 줄의 값 합계 를 합산하려고합니다 .

그래서 내가 바라는 결과는 다음과 같습니다.

2 1019 15 
2 1021 4 
2 1022 9 
2 1030 6 
2 1031 8

나는에 따라 파일을 정렬 할 수 있어요 열이awk또는 sort과 함께 마지막 열 합계 awk하지만 개별 라인하지 두 라인, 열이 일치.


1
열 1은 어떻습니까?
glenn jackman

@glennjackman : 열 1은 각 파일에서 동일한 값을 갖습니다. 파일의 식별자로 사용되며 (그중 45 개가 있음) 일부 다운 스트림 프로세스에 사용됩니다. 내 질문에 대해서는 무시되거나 삭제되고 나중에 다시 추가 될 수 있습니다.
TomPio

또는 $1 $2열쇠로 만드 십시오.
glenn jackman

답변:


12

나는 이것을 Perl에서 할 것이다.

$ perl -lane '$k{"$F[0] $F[1]"}+=$F[2]+$F[3]; 
              END{print "$_ $k{$_}" for keys(%k) }' file 
2 1019 15
2 1021 4
2 1030 6
2 1031 8
2 1022 9

또는 awk :

awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file 

두 번째 열에 따라 출력을 정렬하려면 sort다음으로 파이프하면됩니다 .

awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file | sort -k2

두 솔루션 모두 첫 번째 열도 포함합니다. 아이디어는 첫 번째와 두 번째 열을 해시 (perl) 또는 연관 배열 (awk)의 키로 사용하는 것입니다. 각 솔루션의 핵심은 column1 column2두 줄의 열이 동일하지만 열이 다른 경우 개별적으로 그룹화됩니다.

$ cat file
2 1019 2 3
2 1019 4 1
3 1019 2 2

$ awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file
3 1019 4
2 1019 10

7

어쩌면 이것이 도움이 될 수 있지만 열 1은 항상 2이며 결과는 그것에 달려 있습니까?

awk '{ map[$2] += $3 + $4; } END { for (i in map) { print "2", i, map[i] | "sort -t't'" } }' file

또는 정렬에 대한 의견에서 glenn jackman이 언급 한 바와 같이 :

gawk '{ map[$2] += $3 + $4; } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (i in map) { print 2, i, map[i] } }' file

2
GNU awk가있는 경우을 PROCINFO["sorted_in"] = "@ind_num_asc"파이핑 하는 대신 사용하십시오 sort. 참조 gnu.org/software/gawk/manual/html_node/…
glenn jackman

@taliezin : taliezin과 terdon에게 감사합니다. 두 방법 모두 매력처럼 작동했습니다. 도와 주셔서 감사합니다.
TomPio

1
@ taliezin : 둘 다 나를 위해 일했다고 말하면서, 나는 terdon 답변을 "올바른"답으로 표시했습니다. 당신이 의도 한 것 같아요. 다시 감사합니다.
TomPio

1
총 고유 키를 원하는 질문을 이해하면 카운터를 추가하고 인쇄하면됩니다. awk '{map [$ 2] + = $ 3 + $ 4; } END {for (i에서 맵) {print "2", i, map [i] | "정렬 -t'n '"; cnt ++; } "총 고유 :"cnt} '파일 인쇄
taliezin

1
거의 동일합니다 : awk '{map [$ 2] + = $ 3 + $ 4; oc [$ 2] ++; } END {for (i에서 map) {print "2", i, map [i], oc [i] | "정렬 -t'n '"; }} ', 이제 발생하는 다른 열이 표시됩니다.
taliezin

4

데이터를 미리 정렬하고 awk가 세부 정보를 처리하도록 할 수 있습니다.

sort -n infile | awk 'NR>1 && p!=$2 {print p,s} {s+=$3+$4} {p=$2}'

누산기를 재설정 할 수 있습니다.

sort -n infile | awk 'NR>1 && p!=$2 {print p,s;s=0} {s+=$3+$4} {p=$2}'

산출:

1019 15
1021 19
1022 28
1030 34

정말로 첫 번째 열을 유지하려면 다음과 같이하십시오.

sort -n infile | awk 'NR>1 && p!=$1FS$2 {print p,s} {s+=$3+$4} {p=$1FS$2}'

산출:

2 1019 15
2 1021 19
2 1022 28
2 1030 34

설명

p변수 보유 $2이전 행의 값, 또는 $1FS$2전술 한 두 번째의 경우이다. 이것은 이전 라인의 {print p,s}시점 $2이 현재 라인의 라인과 같지 않다는 것을 의미합니다 ( p!=$2).


첫 번째 열은 서로 다른 값을 한 경우에도 사용할 수 있습니다 sort -k2두 번째 열을 기준으로 정렬
gaoithe

2

스위스 군용 칼 유틸리티 사용 mlr:

mlr --nidx   put '$5=$3+$4'   then   stats1 -g 1,2 -f 5 -a sum   infile

산출:

2   1019    15
2   1021    4
2   1022    9
2   1030    6
2   1031    8

노트:

  • --nidxmlr숫자 필드 이름을 사용하도록 지시 합니다.

  • put '$5=$3+$4'필드 34 의 합인 새로운 5 번째 필드를 만듭니다 .

  • stats1기능 (또는 " 동사 ")보다 작은 만능이며
    중 큰 만능 내의 mlr같은 여러 누산기 기반 함수로, sum, count, mean,

    stats1 -g 1,2컬럼 그룹으로 데이터 12 , 그리고 -f 5 -a sum그 다음 그 그룹의 필드 합계 5 . stats1 명명 된 필드 만 인쇄합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.