여러 행과 열이 있는 파일을 가져와 일치하는 헤더가 있는 열의 값을 가로로 추가(합계)하고 싶습니다. 내 파일(이 예제 아님)에서는 처음 9개 열과 첫 번째 행을 무시합니다. 결과에 영향을 주지 않고 인쇄되기를 원하기 때문입니다.
열은 반복되는 순서가 아니며 예제보다 더 많은 열이 있습니다.
아이디어는 다음과 같습니다.
입력하다:
var x y x y x y
a 1 0 1 1 0 1
b 1 1 0 0 1 1
c 1 1 0 0 0 0
산출:
var x y
a 2 2
b 2 2
c 1 1
내가 지금까지 얻은 것은 다음과 같습니다 ...
awk -F '\t' '{FS==OFS} FNR==1; FNR>1 {for (i=10; i<=NF; i++) {} print}' FILE.tsv > FILE_norepcols.tsv
또한 가능하다면 이 코드를 더 잘 작성하는 방법을 이해하려고 노력 중이므로 변경할 수 있거나 변경해야 하는 사항을 제안해 주세요.
답변1
$ perl -lane '$,="\t";
print(qw/var x y/),next if $. == 1;
push @A, shift @F;
$A[$|--+1] += $_ for @F;
print splice @A;
' file
결과:
var x y
a 2 2
b 2 2
c 1 1
가정:
- 필드 수가 홀수입니다.
- 필드#2 및 후속 필드는 모두 숫자입니다.
설명하다(간단히):
OP에 표시된 대로 제목이 명시적으로 인쇄됩니다.
@A
이 함수를 사용하여 배열을 인쇄할 때 배열을 지워서 각 행의 배열을 다시 채웁니다splice
.배열은 0인덱싱된
@F
입력 레코드의 필드를 저장합니다 .$_
배열의 첫 번째 요소(0번째 요소가 아님)가
@A
배열의 앞쪽에서 이동됩니다@F
. 에서 새 레코드를 읽을 때 마다@F
배열이 생성됩니다perl
. 이는$1, $2, $3, ..., $NF
의 필드 와 유사합니다awk
.배열의 나머지 부분은 배열의 해당 합계를 누적하는
@A
이진 요소 인덱스입니다 .(0|1)+1=>(1|2)
@F
그것이 분명하기를 바랍니다.
답변2
상황을 이해하는 데 도움이 되도록 상당히 긴 변수 이름과 중간 변수를 사용하십시오(각 줄을 주석 처리하거나 나중에 설명을 추가하는 대신).
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==1 {
for (inFldNr=2; inFldNr<=NF; inFldNr++) {
fldName = $inFldNr
if ( !(fldName in fldName2outFldNr) ) {
outFldNr2name[++numOutFlds] = fldName
fldName2outFldNr[fldName] = numOutFlds
}
outFldNr = fldName2outFldNr[fldName]
out2inFldNrs[outFldNr,++numInFlds[outFldNr]] = inFldNr
}
printf "%s%s", $1, OFS
for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
outFldName = outFldNr2name[outFldNr]
printf "%s%s", outFldName, (outFldNr<numOutFlds ? OFS : ORS)
}
next
}
{
printf "%s%s", $1, OFS
for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
sum = 0
for (inFldIdx=1; inFldIdx<=numInFlds[outFldNr]; inFldIdx++) {
inFldNr = out2inFldNrs[outFldNr,inFldIdx]
sum += $inFldNr
}
printf "%s%s", sum, (outFldNr<numOutFlds ? OFS : ORS)
}
}
.
$ awk -f tst.awk file
var x y
a 2 2
b 2 2
c 1 1
답변3
GNU 사용 datamash
:
<file datamash -W transpose |
datamash -W --headers -s -g1 sum 2-4 |
datamash --output-delimiter=' ' transpose
- 공백을 구분 기호로 사용하여 파일 바꾸기(
-W
) - 첫 번째 필드를
-g1
그룹화하고 ( ),-s
그룹화하기 전에 정렬하고( ), 2~4 필드의 값을 합산합니다. 첫 번째 입력 행은 열 머리글로 처리되어 출력(--headers
) 에 인쇄됩니다. - 결과를 바꾸고 탭 문자 대신 공백 문자를 구분 기호로 사용합니다.
산출:
GroupBy(var) x y
sum(a) 2 2
sum(b) 2 2
sum(c) 1 1
결과를 인쇄하려면 다음 명령을 사용하십시오 sed
.
<file datamash -W transpose |
datamash -W --headers -s -g1 sum 2-4 |
datamash --output-delimiter=' ' transpose |
sed 's/^[^(]*(\([^)]*\))/\1/'
산출:
var x y
a 2 2
b 2 2
c 1 1
다음 cut
명령을 사용하여 입력 파일에서 처음 9개 열을 제거하고 결과에 다시 추가할 수 있습니다 paste
.
paste -d ' ' <(cut -d' ' -f-9 file) <(cut -d' ' -f10- file | datamash ... )
head -n1
print를 사용하고 추가 헤더 줄을 건너뛸 수 있습니다 tail -n+2
.
{
head -n1 file
paste -d ' ' <(tail -n+2 file | cut -d' ' -f-9) <(tail -n+2 file | cut -d' ' -f10- | datamash ... )
}