1つの列(長い)をさまざまな長さの複数の列(短い)に変換する

1つの列(長い)をさまざまな長さの複数の列(短い)に変換する

1つのデータ列(つまり、1行につき1つのデータ値)を含むファイルがあります。私はこのデータをいくつか解釈します。データセット; データセットはNA1 つ以上の行に分けられます。データセットの長さはさまざまです。これを複数列形式に変換したいと思います。ここで、各データセットは、入力ファイルに表示されるのと同じ順序で列にあります。

たとえば、次のファイルがあります(実際には、このファイルにはより多くのデータが含まれています)。

NA
4
3
5
7
8
3
NA
NA
NA
3
4
5
2
NA
2 
7
4
6
9
NA

私の予想結果は次のとおりです。

4 3 2
3 4 7
5 5 4
7 2 6
8 . 9
3

8と9の間の点は実際には必要ありませんが、スペースで置き換えることができます。

答え1

awk各データセット(データがNA行の間にある)を別々のファイルに分割し、行をスキップしてNA一緒に入れるpasteことができます。

awk '/^NA$/ && !NA{N++; NA=1; next} !/^NA$/{print >"file"N; NA=0}
    END{system("paste file*")}' inile.txt

このNAフラグは、ファイルを順次生成するために使用され、以下で使用できます。

awk '/^NA$/{N++; next} !/^NA$/{print >"file"N}
    END{system("paste file*")}' inile.txt

出力は次のとおりです

4 3 2
3 4 7
5 5 4
7 2 6
8   9
3

答え2

この出力形式は私には適していません。私はこれがまったく実用的ではないと思います。

とにかく、1行に書き込んで次のように置き換えます(またはより良い方法は1行に保つことです)。

tr '\n' ' ' < example | tr 'N' '\n' | sed 's/^A //; /^$/d'

与えられた

4 3 5 7 8 3 
3 4 5 2 
2 7 4 6 9

答え3

シェルから変換するのは痛いです。以下はPerlの短い答えです。配列::転置::非定型CPANから

perl -MArray::Transpose::Ragged=transpose_ragged -lnE '
        if (/NA/) { $n++; next }      # next row
        push @{$data[$n]}, $_;        # creating the 2D matrix of data
    } END {
        say join "\t", @$_ for transpose_ragged [grep {defined} @data];
' file

別のアプローチは次のとおりです。以前のパイプラインはgawk基本的に@n.caillouの答えと同じで、awkコードが変更されました。

paste -sd " " file | sed 's/NA/\n/g' | sed '/^ *$/d' | gawk '
    {
        for (i=1; i<=NF; i++) data[FNR][i] = $i
        if (NF > max) max = NF
    }
    END {
        for (i=1; i<=max; i++) {
            for (j=1; j<=NR; j++) printf "%s\t", data[j][i]
            print ""
        }
    }
'

GNU awkを使用した多次元配列の処理

答え4

これGNUデータの混合バージョン 1.1.1 が必要です。バージョン 1.0.7 では正しく動作しません。

#!/bin/bash

tr '\n' ' ' < input.txt |
sed 's/\s*NA\s*/\n/g;' |
sed '/^$/d'  |
datamash --no-strict --filler="." -W -t' ' transpose

説明する

  1. tr '\n' ' ' < input.txt- すべての改行を空白に置き換えます。つまり、すべての行を1つの行にリンクします。
  2. sed 's/\s*NA\s*/\n/g;'- すべての「NA」に隣接するスペースを改行文字に置き換えます。つまり、大きな行を複数の行に分割し、各行は水平に書かれた将来の列です。
  3. sed '/^$/d'- 空白行をすべて削除します。
  4. datamash --no-strict --filler="." -W -t' ' transpose
    • --no-strict- フィールド数が異なる行を許可する
    • --filler="."- 欠けている値をポイントで埋めます。スペースに変更されることがあります。
    • -W- スペース(1つ以上のスペースおよび/またはタブ)を入力フィールド区切り文字として使用します。
    • -t' '- 出力フィールド区切り記号としてタブの代わりにスペースを使用します。
    • transpose- 行を列に変換します。

入力する

NA
4
3
5
7
8
3
NA
NA
NA
3
4
5
2
NA
2
7
4
6
9
NA

出力

4 3 2
3 4 7
5 5 4
7 2 6
8 . 9
3 . .

関連情報