각 열의 각 uniq 문자열의 총 개수(합계)를 가져오고 해당 열 순서로 출력하려고 합니다.
다양한 전체 입력이 수천 개의 행과 열인 경우가 많기 때문에 강력한 awk 명령에서 이것을 사용해야 합니다.
나는 이것을 직접 시도했지만 운이 없었습니다. 나는 꽤 가깝다고 생각합니다. 분명히 작동하지 않지만 코드를 사용하는 곳은 다음과 같습니다.
awk -F ',' '{ for(N=1; N<=NF; N++) {{count[$N]++} END {for (word in count) print word, count[word]}}}'
위 코드에 대한 내 생각은 실행하면 지정된 단일 열에 대해 원하는 출력을 얻을 수 있다는 것입니다. 이제 열 2를 가정해 보겠습니다.
awk '{count[$2]++} END {for (word in count) print word, count[word]}'
하지만 각 열에 대해 이러한 유형의 출력이 필요합니다. 그래서 이것을 달성하기 위해 열을 반복하려고 시도했지만 실패했습니다.
다음은 몇 가지 샘플 데이터입니다.
입력 예:
M,M,M,M
N,N,N,N
A,M,G,L
P,P,P,P
A,N,G,L
P,N,P,L
A,A,A,A
C,C,C,C
A,M,G,C
L,L,L,L
G,G,G,G
해당 예상 출력:
M 1,M 2,M 1,M 1
N 1,N 2,N 1,N 1
A 3,A 1,A 1,A 1
P 1,P 1,P 1,P 1
L 1,L 1,L 1,L 3
G 1,G 1,G 3,G 1
C 1,C 1,C 1,C 1
출력을 설명하기 위해 예제 입력의 첫 번째 열에는 As가 3개 있고 다른 모든 문자는 각각 1개만 있으므로 해당 열의 출력은 다음과 같습니다.
M 1
N 1
A 3
P 1
L 1
G 1
C 1
이 코드를 작성했는데 작동하지만 이상적으로는 awk 명령에서 구현하고 싶습니다.
for i in $(seq $NumberOfColumns);do
ColumnOutput=$(awk -F ',' -v x=$i '{count[$x]++} END {for (word in count) print word, count[word]}' file)
TotalOutput=$(paste <(echo "$TotalOutput") <(echo "$ColumnOutput") -d ,)
done
echo "$TotalOutput" | sed 's/^,//g'
답변1
나는 이것이 도움이 될 것이라고 생각합니다:
$ awk -F"," '
NR==FNR { for (i=1;i<=NF;i++) {a[i,$i]+=1;b[$i]=$i} next }
{ for (i=1;i<=NF;i++)if(b[$1]) printf "%s %s,",$1,a[i,$1];else next; print ""; delete b[$1] }
' file file
M 1,M 3,M 1,M 1,
N 1,N 3,N 1,N 1,
A 4,A 1,A 1,A 1,
P 2,P 1,P 2,P 1,
C 1,C 1,C 1,C 2,
L 1,L 1,L 1,L 3,
G 1,G 1,G 4,G 1,
답변2
사용행복하다(이전 Perl_6)
~$ raku -e 'my @a = [Z] lines.map: *.split(","); my @b; \
for ^@a -> $row { \
for ^$row.elems -> $col { my %h; \
%h{$_}++ for @a[$row]>>.[$col]; \
@b.push: %h.sort }}; \
for ^@b>>.elems.max -> $j { \
put @b.map({ $_.[$j] // (" " => "0") }).join: "," };' file
또는 (더 쉽게):
~$ raku -e 'my @a = [Z] lines.map: *.split(","); my @b; \
for ^@a -> $row { \
my %h is BagHash = @a[$row]; \
@b.push: %h.sort }; \
for ^@b>>.elems.max -> $j { \
put @b.map({ $_.[$j] // (" " => "0") }).join: "," };' file
다음은 Perl 계열의 프로그래밍 언어인 Raku로 작성한 답변입니다. Raku에는 유니코드에 대한 고급 지원 기능이 내장되어 있습니다. 위의 코드는 @
서명된 배열 및 %
서명된 해시(예: 사전/키-값 쌍) 와 같은 다양한 Perl 기능을 활용합니다 .
먼저, 데이터를 한 줄씩 읽어서
lines
각 데이터를split
쉼표로 구분합니다. 행과 열을 바꾸려면[Z]
연산자를 사용하고 데이터를@a
배열에 저장하십시오.다음으로
@a
배열은 먼저 by,$row
다음으로 반복$col
되어 각$row
셀에 대해 "키"( ) 가 해시(첫 번째 답변) 또는 BagHash(두 번째 답변)$_
에 저장됩니다 .%h
각 행이 구문 분석된 후 키/값 데이터가@b
배열에 저장됩니다.마지막으로
max
키/값의 수를 결정하고(통과) 데이터를 출력합니다. 특정 열의 키가 정의되지 않은 곳에 0을 삽입하도록 주의합니다(OP는 여기에서 대신 사용할 수 있음).elems
put
0
"Nil"
" "
입력 예(열의 키 개수가 같지 않음):
M,M,M,M
N,N,N,N
A,M,G,L
P,P,P,P
A,N,G,L
P,N,P,L
A,A,A,A
C,C,C,C
A,M,G,X
L,L,L,L
G,G,G,G
출력 예(키/값 쌍 \t
탭으로 구분됨):
A 4,A 1,A 1,A 1
C 1,C 1,C 1,C 1
G 1,G 1,G 4,G 1
L 1,L 1,L 1,L 4
M 1,M 3,M 1,M 1
N 1,N 3,N 1,N 1
P 2,P 1,P 2,P 1
0, 0, 0,X 1
https://docs.raku.org/type/BagHash
https://docs.raku.org
https://raku.org