다음 패턴의 파일이 있습니다
a 12
a 13
a 15
a 14
b 5
b 6
c 2
c 5
아래와 같이 첫 번째 열을 기준으로 그룹화하고 싶습니다.
a 12 13 15 14
b 5 6
c 2 5
제안해주세요
답변1
데이터가 (질문에서와 같이) 첫 번째 열을 기준으로 정렬되었다고 가정하고 GNU를 사용하여 datamash
공백으로 구분된 첫 번째 열을 기준으로 그룹화하고 두 번째 열을 축소합니다.
$ datamash -W groupby 1 collapse 2 <file
a 12,13,15,14
b 5,6
c 2,5
원하는 출력을 얻으려면 결과의 첫 번째 열 뒤의 탭과 쉼표를 공백으로 바꾸십시오.
$ datamash -W groupby 1 collapse 2 <file | tr '\t,' ' '
a 12 13 15 14
b 5 6
c 2 5
입력이 첫 번째 열을 기준으로 정렬되지 않은 경우 sort
데이터가 먼저 전달되거나 ( ) 옵션 datamash
과 함께 사용됩니다.-s
--sort
당신은 또한 사용할 수 있습니다밀러( mlr
)그리고 그것의nest
작업. 이 함수를 사용하면 두 번째 열의 값을 첫 번째 열의 각 고유 값을 공백으로 구분한 목록으로 "내포"할 수 있습니다.
$ mlr --nidx nest --implode --values --across-records --nested-fs space -f 2 file
a 12 13 15 14
b 5 6
c 2 5
또는 --ivar
Miller 버전 5.5.0 이상에서 약어를 사용하십시오(6.0.0 제외).부서진):
$ mlr --nidx nest --ivar space -f 2 file
a 12 13 15 14
b 5 6
c 2 5
데이터를 미리 정렬할 필요는 없습니다.
답변2
사용 awk
(입력 파일이 첫 번째 열을 기준으로 정렬된 경우):
awk '{ printf "%s", (NR==1 || pre!=$1? (NR>1? ORS:"")$1: "") OFS $2; pre=$1 }
END { print "" }' infile
awk
+를 사용합니다 sort
(입력 파일이 첫 번째 열로 정렬되지 않은 경우).
<infile sort|
awk '{ printf "%s", (NR==1 || pre!=$1? (NR>1? ORS:"")$1: "") OFS $2; pre=$1 }
END { print "" }'
아니면 awk
정렬된 입력이나 정렬되지 않은 입력을 사용하세요.
awk '{ grp[$1]= (grp[$1]==""?"":grp[$1] OFS) $2 }
END { for(x in grp) print x, grp[x] }' infile
답변3
사용행복하다(이전 Perl_6)
raku -e 'lines.map(*.words).map(*.hash).classify( *.keys, :as{$_.values} ).put;'
입력 예:
a 12
a 13
a 15
a 14
b 5
b 6
c 2
c 5
예제 출력:
a 12 13 15 14
b 5 6
c 2 5
아래는 코딩된 솔루션입니다.행복하다, Perl 프로그래밍 언어 계열의 구성원입니다. 위의 코드는 2열 목록의 (간단한) 사례를 처리합니다(아래에서 보다 일반적인 솔루션에 대한 설명).
보다 일반적인 솔루션(두 개 이상의 열 입력 포함)의 경우 lines
행별로 읽고, words
합계의 요소를 append
해시 로 나누고 %h
, =>
(굵은 화살표) 해시 생성자를 사용하여 키(왼쪽)와 값(오른쪽)을 묘사합니다. 특수 할당 연산자를 사용하면 .=
먼저 별도로 선언하는 단계가 생략됩니다. my %h;
그런 다음 hash 를 classify
사용하여 반환 값을 기록합니다(그렇지 않으면 전체 키-값 쌍이 반환됩니다).%h
key
:as
raku -e 'my %h.=append(.words[0] => .words[1..*]) for lines; %h.classify(*.keys, :as{$_.values}).put;'
warpbreaks
R 프로그래밍 언어의 데이터(54행, 3열) 와 같은 작은 데이터 세트에 대해 위 코드를 실행합니다. 여기서 두 번째 열은 두 가지 유형의 양모인 " A
" 및 " B
"을 나타냅니다.
- [입력 파일은 다음과 같습니다:
warpbreaks
with를 사용하여 내보낸 데이터 세트, 큰따옴표 제거를 위한 후처리, 쉼표를 탭으로 변환].R
write.csv
row.names=FALSE
아래에서 작업 중인 Raku 코드(및 반환)입니다. -ed 키가 아닌 value
열을 사용하는 방법(또는 동일 조인을 사용하는 방법)에 유의하세요.join
"|"
join(",")
~$ raku -e 'my %h.=append(.words[1] => .words[0,2].join("|") ) for lines.skip(1); %h.classify(*.keys, :as{$_.values}).put;' warpbreaks_no_quotes.tsv
A 26|L 30|L 54|L 25|L 70|L 52|L 51|L 26|L 67|L 18|M 21|M 29|M 17|M 12|M 18|M 35|M 30|M 36|M 36|H 21|H 24|H 18|H 10|H 43|H 28|H 15|H 26|H
B 27|L 14|L 29|L 19|L 29|L 31|L 41|L 20|L 44|L 42|M 26|M 19|M 16|M 39|M 28|M 21|M 39|M 29|M 20|H 21|H 24|H 17|H 13|H 15|H 15|H 16|H 28|H
https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/warpbreaks.html
https://docs.raku.org/routine/classify
https://raku.org
답변4
awk의 연관 배열을 사용하는 것이 더 쉬운 옵션일 수 있습니다.
$ awk '{k[$1]=k[$1]" "$2} END {for (i in k) print i k[i]}' infile
a 12 13 15 14
b 5 6
c 2 5