大容量のcsvファイルがあり、簡単なランキングを作成したいと思います。
$ cat file.csv
2022-12-01 RED 1
2022-12-01 RED 1
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 YELLOW 1
2022-12-01 YELLOW 1
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
$ sort file.csv | uniq -c | sort -nr > file_sort.csv
$ cat file_sort.csv
3 2022-12-01 RED 2
3 2022-12-01 YELLOW 2
2 2022-12-01 RED 1
2 2022-12-01 YELLOW 1
結果を新しい列として追加したいのですが、次のように既存の$1に追加したいと思います。
$ cut -f1 file_sort.csv
3 2022-12-01
3 2022-12-01
2 2022-12-01
2 2022-12-01
uniq行の値を新しい列として保存する方法はありますか?このように:
$ cut -f1 file_sort.csv
3
3
2
2
答え1
あなたが望むのは、最初のフィールドから最後のフィールドに数字を移動することだけです。これを指定しませんが、cut
表示されたコマンドを使用すると、ファイルがタブで区切られていることを意味します。そのuniq -c
場合は、出力が空白(表示されていない)で行を埋め、発生後にタブを追加しないことを考えると、次のように簡単に操作できます。
$ sort file.csv | uniq -c | sort -nr | perl -pe 's/^\s+(\d+) (.*)/$2\t$1/'
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
または以下sed
をサポートします-E
。
$ sort file.csv | uniq -c | sort -nr | sed -E 's/^ *([0-9]*) (.*)/\2\t\1/'
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
そしてどんなsedでも:
$ sort file.csv | uniq -c | sort -nr | sed 's/^ *\([0-9]*\) \(.*\)/\2\t\1/'
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
または、数を計算してawk
目的の場所にフィールドを追加してから、4番目のフィールドに基づいてソートすることもできます。
$ awk -F'\t' -v OFS='\t' '{ cnt[$0]++ }
END{
for(line in cnt){
print line,cnt[line]
}
}' file.csv | sort -nrk4,4
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
答え2
使用幸せ(以前のPerl_6)
あなたが望むのはBag
要素です。この場合、要素は次のとおりですlines
。
~$ raku -e '.say for lines.Bag;' file
入力例(タブ区切り):
2022-12-01 RED 1
2022-12-01 RED 1
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 YELLOW 1
2022-12-01 YELLOW 1
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
出力例:
2022-12-01 RED 2 3
2022-12-01 RED 1 2
2022-12-01 YELLOW 2 3
2022-12-01 YELLOW 1 2
注:ここでの実際の問題は末尾のスペースである可能性があります。trim-trailing
各行の右端にスペースを削除する呼び出しを追加できます。
~$ raku -e '.put for lines.map(*.trim-trailing).Bag;'
#OR
~$ raku -e '.put for lines>>.trim-trailing.Bag;'
答え3
count-distinct
Miller()サブコマンドを使用して、mlr
入力がタブで区切られ、列見出しがないと想定し、最初の3つのフィールドに一意の値を持つレコード数を計算します。
$ mlr --tsv -N count-distinct -f 1,2,3 file
2022-12-01 RED 1 2
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 YELLOW 2 3
カウントは、フィールドリストの末尾に新しいフィールドとして追加されます。入力をソートする必要はありません。
カウントを最初のフィールドとして使用するには、reorder
サブコマンドを使用します。タイトルが出力に表示されない場合でも、ジョブcount
で生成された名前付きフィールドを参照できます。count-distinct
$ mlr --tsv -N count-distinct -f 1,2,3 then reorder -f count file
2 2022-12-01 RED 1
3 2022-12-01 RED 2
2 2022-12-01 YELLOW 1
3 2022-12-01 YELLOW 2
答え4
awkコマンドの連想配列のアイデアを使用すると、一意の行数を簡単に計算できます。
$ awk '{a[$0]++} END {for (i in a) print a[i]"--->",i}' infile
2---> 2022-12-01 YELLOW 2
3---> 2022-12-01 RED 2
2---> 2022-12-01 YELLOW 1
1---> 2022-12-01 YELLOW 2
2---> 2022-12-01 RED 1