次のパターンのファイルがあります
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
グループ化し、2番目の列を縮小します。
$ 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
仕事。この関数を使用すると、2 番目の列の値を、最初の列の各固有値をスペースで区切られたリストに「埋め込む」ことができます。
$ 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列)などの小さなデータセットに対して上記のコードを実行します。ここで、2番目の列は2つのタイプのウール、「」とA
「B
」を表します。
- [入力ファイルは次のとおりです。with
warpbreaks
を使用してエクスポートされたデータセット、二重引用符を削除するための後処理、コンマをタブに変換]。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