다음과 같은 파일이 있습니다.
2017-07-30 A
2017-07-30 B
2017-07-30 B
2017-07-30 A
2017-07-30 A
2017-07-30 C
2017-07-31 A
2017-07-31 B
2017-07-31 C
2017-07-31 B
2017-07-31 C
각 줄은 사건(A, B, C)과 사건이 발생한 날짜를 나타냅니다. 하루에 각 유형의 이벤트 수를 계산하고 싶습니다. 이는 를 통해 수행할 수 있으며 sort file | uniq -c
출력은 다음과 같습니다.
3 2017-07-30 A
2 2017-07-30 B
1 2017-07-30 C
1 2017-07-31 A
2 2017-07-31 B
2 2017-07-31 C
그러나 각 이벤트 유형을 열로 사용하고 싶습니다.
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
이 작업을 수행할 수 있는 매우 일반적인 명령줄 도구가 있습니까?필요한 경우 모든 이벤트 유형(A, B, C)을 미리 알고 있다고 가정할 수 있지만, 그렇지 않은 경우에는 그게 더 좋습니다. 다시 말하지만, 각 이벤트가 하루에 한 번 이상 발생한다고 가정할 수 있지만(출력에 0이 없음을 의미), 이것이 필요하지 않다면 여기서는 괜찮습니다.
답변1
"상당히 일반적"에 다음이 포함되는 경우GNU 데이터 혼합, 그 다음에
datamash -Ws crosstab 1,2 < file
전임자.
$ datamash -Ws crosstab 1,2 < file
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
(불행히도 웹사이트 형식은 탭을 유지하지 않습니다. 실제 출력은 탭 정렬입니다.)
답변2
앗해결책:
awk '{ d[$1]; k[$2]; a[$2,$1]++ }END{
printf("%10s"," ");
for(i in k) printf("\t%s",i); print "";
for(j in d) {
printf("%-10s",j);
for(i in k) printf("\t%d",a[i,j]); print ""
} }' file
산출:
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
답변3
더 짧은 버전에서는 null 값을 0에 할당하지 않습니다.
perl -lane '
++$h{$i[!$h{$F[0]} ? @i : -1]=$F[0]}{$F[1]}}{
print join "\t", "\t", @h = sort keys %{ +{ map { map { $_ => 1 } keys %$_ } values %h } };
print join "\t", $_, @{$h{$_}}{@h} for @i;
' yourfile
perl -lane '
$i[@i]=$F[0] unless $h{$F[0]};
++$h{$F[0]}{$F[1]}}{
@h = sort keys %{ +{ map { map { $_ => 1 } keys %$_ } values %h } };
print join "\t", "\t", @h;
for my $date ( @i ) {
my $href = $h{$date};
print join "\t", $date, map { $href->{$_} || 0 } @h;
}
' yourfile
결과
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
데이터 구조:
%h
키가 A, B, C 등인 날짜와 값을 포함하는 해시 하위 해시keys
이며 해당 값은 해당 특정 날짜에 대한 각각의 개수입니다.
%h = (
2017-07-30 => {
A => 3,
B => 2,
C => 1,
},
...
);
@i
날짜가 발생한 순서대로 저장하는 배열입니다.@i
이전에 본 적이 없거나 처음으로 본 경우에만 날짜를 배열에 푸시합니다. 순서는 배열 위치에 따라 제공됩니다.@h
해시의 모든 "A", "B", "C" 등의 키를 합산한 후 배열은 고유한 키를 갖게 됩니다%h
.
답변4
용법: ./count.awk input.txt | column -t -n
#!/usr/bin/gawk -f
{
dates[$1] = $1;
events[$2] = $2;
numbers[$1][$2]++;
}
END {
num_dates=asort(dates);
num_events=asort(events);
for (i = 1; i <= num_events; i++) {
printf " %s", events[i];
}
print "";
for (i = 1; i <= num_dates; i++ ) {
printf "%s ", dates[i];
for (j = 1; j <= num_events; j++) {
printf "%s ", numbers[dates[i]][events[j]];
}
print "";
}
}
시험:
입력하다(테스트가 복잡함)
2017-07-30 A
2017-07-30 D
2017-07-29 D
2017-07-30 B
2017-07-28 E
2017-07-30 B
2017-07-30 A
2017-07-30 A
2017-07-30 C
2017-07-31 A
2017-07-31 B
2017-07-31 C
2017-07-31 B
2017-07-31 C
산출
A B C D E
2017-07-28 1
2017-07-29 1
2017-07-30 3 2 1 1
2017-07-31 1 2 2