共有一致列を行に変換

共有一致列を行に変換

次の構造のファイルがあります。

Locus7625186 GO0004866
Locus7625186 GO0010951
Locus7625186 GO0005615
Locus7625186 GO0016021
Locus7360093 GO0004712
Locus7360093 GO0007093
Locus1507198 GO0044212
Locus1507198 GO0045944
Locus1507198 GO0005634
Locus1507198 GO0036464
Locus1507198 GO0046982

これを次のように変換する必要があります。

Locus7625186 GO0004866 GO0010951 GO0005615 GO0016021
Locus7360093 GO0004712 GO0007093
Locus1507198 GO0044212 GO0045944 GO0005634 GO0036464 GO0046982

GOxxxxxxx同じ最初の列を共有する一致の数は異なります。

答え1

そしてGNUデータ統合

$ datamash -W groupby 1 collapse 2 < file | sed 's/,/ /g'
Locus7625186    GO0004866 GO0010951 GO0005615 GO0016021
Locus7360093    GO0004712 GO0007093
Locus1507198    GO0044212 GO0045944 GO0005634 GO0036464 GO0046982

(デフォルトのカンマ区切り文字が気に入らない場合は、sedからパイプを省略できます)。

答え2

GNU sedストリームエディタを使用してこの問題を解決できます。

sed -Ee '
   :a
      $!N
      s/^((\S+)\s.*)\n\2(\s.*)/\1\3/
   ta
   P;D
' file

結果

Locus7625186 GO0004866 GO0010951 GO0005615 GO0016021
Locus7360093 GO0004712 GO0007093
Locus1507198 GO0044212 GO0045944 GO0005634 GO0036464 GO0046982

これは次の方法で行うこともできますPOSIX sed

sed -e '
   :a
      $!N
      s/^\(\([^[:space:]]\{1,\}\)[[:space:]].*\)\n\2\([[:space:]].*\)/\1\3/
   ta
   P;D
' file

答え3

sed小さくてポータブルで奇妙な別のアプローチは次のとおりです。

sed 'N;/^\(.*\)\( .*\)\(\n\1\)/!P;s//\3\2/;D'
  • このN;P;D方法を使用すると、パターンスペースに常に2行があるため、N次の行を最初に追加します。
  • /^\(.*\) .*\n\1/単語、空白、他の単語、改行、および繰り返される最初の単語で始まる行を一致させるため、バッファの2行は最初の(Locus)単語を共有します。そうでない場合(!P、最初の行は完成したものとして印刷され、後で次のように削除できます。D
  • ただし、行が一致する場合は、最初の単語が同じ2行あり、改行と重複する単語を削除して置換を実行できます。だから私はアドレスパターンに2つのサブグループを追加したので、これをP繰り返すことなく空のパターンを使用して再利用します。
  • これでトリックが出ます。パターンスペースに空の最初の行があり、その後に最初の単語とこれまでに持っていたすべての2番目の単語を含む2番目の行があるようにfirst second\nfirst置き換えます。\nfirst second次に、空Dの最初の行を削除し、これまでに収集された行を引き続き使用します。これを一致に含めると交換する必要がないため、\n移植性はありません。\3\n

答え4

awk '!a[$1]{b[++p]=$1; a[$1]=$2;next} {a[$1]=sprintf("%s%s%s", a[$1], OFS, $2)} END {for (i=1; i<=p; i++) print b[i], a[b[i]]}' file

この記事に基づいて最初のフィールド/要素に基づいて行をグループ化する方法

関連情報