複数行を単一行に合計

複数行を単一行に合計

csvファイルの複数の行を1行にまとめる方法は?私はSQLでクエリを実行しましたが、うまくいきますが、Linuxで同じ効果を得る方法がわかりません。

私の現在のファイルは次のとおりです。

swainb02,Ben Swain,1015
swainb02,Ben Swain,1016
swainb02,Ben Swain,1018
swainb02,Ben Swain,1020
shaiks21,Sarah Shaikh,0073
shaiks21,Sarah Shaikh,0080
shaiks21,Sarah Shaikh,0082

複数のユーザーが複数の地域コードにアクセスできます。私が探しているのは、読みやすくするためのより簡単なバージョンのファイルです。

希望の出力:

swainb02,Ben Swain,1015,1016,1018,1020
shaiks21,Sarah Shaikh,0073,0080,0082

この問題を解決する方法を知っていますか?ありがとう

答え1

入力が質問に示されているようにキー値にグループ化されているとし(最初に入力をソートしない場合)、すべてのUnixシステムのすべてのシェルでawkを使用すると、入力ファイルのサイズに関係なくほとんど問題はありません。メモリ使用:

$ cat tst.awk
BEGIN { FS=OFS="," }
{ curr = $1 OFS $2 }
curr != prev {
    printf "%s%s", ors, curr
    prev = curr
    ors = ORS
}
{ printf "%s%s", OFS, $3 }
END { printf ors }

$ awk -f tst.awk file
swainb02,Ben Swain,1015,1016,1018,1020
shaiks21,Sarah Shaikh,0073,0080,0082

答え2

awk結果に対して小さなスクリプトを実行します。

awk -F, '
$1$2 != Last    {printf DL "%s", $0
                 Last=$1$2
                 DL=ORS
                 next
                }
                {printf ",%s", $3
                }
END             {print ""
                }
' file
swainb02,Ben Swain,1015,1016,1018,1020
shaiks21,Sarah Shaikh,0073,0080,0082

新しいユーザーのデータを一度印刷し、次のユーザーに会うまで市外局番を追加します。

答え3

入力がカンマ、改行、または引用符を含まない単純なCSVであると仮定すると、GNUを使用してdatamash最初の2つのカンマ区切りフィールドをグループ化し、3番目のフィールドを折りたたむことができます。

$ datamash -t, groupby 1,2 collapse 3 <file
swainb02,Ben Swain,1015,1016,1018,1020
shaiks21,Sarah Shaikh,0073,0080,0082

これは、データが最初の2つのフィールドにソートされていると仮定します(または、サンプルデータに示すように、一緒にソートされたレコードがファイル内の隣にあると仮定します)。それ以外の場合は、sort -t, -k 1,2データが最初に渡されるか、対応するdatamash-sまたは--sort)オプションと一緒に使用されます。


汎用CSV入力の場合は、Miller()などのCSV認識ツールを使用してくださいmlr。以下は上記と同じことを行います。

$ mlr --csv -N nest --ivar comma -f 3 file
swainb02,Ben Swain,"1015,1016,1018,1020"
shaiks21,Sarah Shaikh,"0073,0080,0082"

CSV をサポートしているので、mlr組み合わせの 3 番目のフィールドと含まれているコンマを正しく引用します。

答え4

この awk バージョンは行の順序に関係なく動作します。

{
  if ($1 "," $2 in a) {
    a[$1 "," $2] = a[$1 "," $2] "," $3
  } else {
    a[$1 "," $2] = $3
  }
}

END {
  for (i in a) {
    print i, a[i]
  }
}

一方、csvkitはより正確な結果を出力します。

csvsql -H -d ',' --query 'SELECT a,b, GROUP_CONCAT(c) as c FROM data GROUP BY a, b' data.txt
a,b,c
shaiks21,Sarah Shaikh,"73.0,80.0,82.0"
swainb02,Ben Swain,"1015.0,1016.0,1018.0,1020.0"

引用符がない場合はさらに表示できますが、他の例では、1行あたりのフィールド数が異なる場合があります。さらに処理するには、定義された3番目のフィールドを持つ出力が非常に望ましいです。

関連情報