awkを使用して同一列の数を識別する

awkを使用して同一列の数を識別する

それぞれ 6 つの列 (行数は異なる場合があります) を含む個別のファイルが多数あります。簡単な例として、次のようになります。

1   0   0   0   0   0

0   1   1   1   0   0

固有の列がいくつあるか (つまり、数字とその順序が一致するか) を特定しようとしています。この場合は 3 になります。

これを実行するための簡単なワンライナーはありますか? ある列を別の列と比較するのは簡単ですが、同一の列を見つけるにはどうすればよいのでしょうか?

答え1

次のパイプを使用して一意の列をカウントできます。

$ awk '{for (i=1; i<=NF; ++i) a[i]=a[i]$i; } END { for (i in a) print a[i] }' foo \
  | sort -u | wc -l

awk コマンドは入力を転置し、結果の行をソートして、一意の行のみが保持され ( -u)、最後にすべての (一意の) 行 (つまり、転置された列) がカウントされます ( wc -l)。

NFは組み込みの awk 変数であり、現在のレコードのフィールド数に自動的に設定されることに注意してください。$iは i 番目のフィールドを参照し、ENDすべてのレコードが処理された後に実行されるように次のブロックを保護します。awk はデフォルトで空白と非空白のフィールド区切りを使用します。

答え2

(((...)))、しかし、同一の列をどのように見つけるのでしょうか?

$ printf '%s\n' '1 0 0 0 0 0' '0 1 1 1 0 0' | awk -vSUBSEP='=' '
    { for (i=1; i<NF; i++)
        for (j=i+1; j<=NF; j++)
          if ($i==$j)
            M[i,j]++
    }
    END{ for (m in M) if (M[m]==NR) print m }'
5=6
2=3
2=4
3=4

i<j各行のすべての列について、M[i,j]それらの列の値が等しい場合は常に増分します。つまり、行M[i,j]==NRを読み取った後はNR、読み取ったすべての行の値が同一であることを意味します。

答え3

この質問は私を興味深くさせ、私は正確には理解できなかったアプローチに従いたいと思ったのですが、素晴らしい助けを得ました別の質問として投稿した後私が投稿した質問から、私が取ろうとしているアプローチを理解できると思います。

この問題に対する解決策があと2つ見つかりました(1つはグヌーク答えはパール解決策と別の解決策 ジョンの私の解決策と組み合わせた解決策。

#The variable appended_input will remove spaces/tabs and just append the rows. 
#Modify the file name in this line. Here I use inputfile as the filename. 

appended_input=$(column -s '\t' inputfile | tr -d '[:space:]') ;

#The array variable will store each column-wise value as an array element.  
#I use sort to find the number of unique elements.

array=($(
    for ((i=0; i<6; i++))
    do
        new=${appended_input:$i:1}
        for ((j=i+6; j<${#appended_input}; j=j+6))
        do 
            new="$new${appended_input:$j:1}"
        done
        echo "$new"
    done
    )) | echo "${array[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '

テスト

入力ファイルは以下のとおりです。

1 0 0 1 0 0
0 1 1 0 0 0
1 1 1 1 1 0
1 0 0 1 0 1
1 0 0 1 0 1

上記のスクリプトを実行すると、次のような出力が得られます。

00011 00100 01100 10111

最終パイプとしてを使用するwc -wと、上記のような一意の列値ではなく、出力は 4 のみになります。

答え4

これはgawk、コプロセスを使用して各列を の個別のインスタンスにフィードしsha256sum、一意のハッシュの合計数を報告するソリューションです ( とのハッシュ衝突の可能性はsha256sum統計的に重要ではないため、一意のハッシュの数は一意の列の数と一致するはずです)。これはひどいハックだと考える人もいるかもしれませんが、このアプローチが他のアプローチよりも優れている点の 1 つは、データの連結/転置を試みないため、比較的メモリ効率が高いことです。

awk 'BEGIN{for(i=1; i<=6; ++i){s=sprintf("%*s", i+1, ""); a[i]="sha256sum"s}}
    {for (i=1; i<=6; ++i) print $i |& a[i]}
    END{com= "sort | uniq | wc -l"
    for (i=1; i<=6; ++i){close(a[i], "to"); a[i] |& getline x;
    close(a[i]); print x | com};
    close(com)}' file 

関連情報