最初の行に基づいて列をソートする方法は?

最初の行に基づいて列をソートする方法は?

非常に大きなデータセット(1000行と700000列)の列を並べ替える必要があります。たとえば、col1 col4 col3 col2など、ランダムに配置された列があり、それらをソートする必要があります。

私は成功せずにいくつかのコマンドを試しました。

例:

ID M2 M5 M8 M1 M3 M9 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln

この例では、ポイントは列と線が多いことを意味します。同様に、次のように列を並べ替える必要があります。

ID M1 M2 M3 M4 M5 M6 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln

ありがとう

答え1

GNUと共にdatamashそしてGNU sort

datamash transpose -t ' ' -H <file_in.csv | sort -V | datamash transpose -t ' ' -H >file_out.csv

これは「かなり小さい」データに適しています。あなたのファイルにうまくいくかもしれませんし、うまくいかないかもしれません。

編集する:前置きのない次のソリューションは、あまりにも多くのリソースを占有してはいけません。

答え2

perl -pale '
   $. == 1 and
   @I = map  { $_->[1] }
        sort { $a->[0] <=> $b->[0] }
        map  { [ $F[$_] =~ /^M(\d+)$/, $_ ] } 1..$#F;
   $_ = "@F[0, @I]";
' yourlargefile

  1. 最初の行に対してMWell Knownを使用すると、Schwartzian maneuver列が数値ソート順(M1、M2、M3、...)で表示されるように並べ替えられたインデックスが提供されます。
  2. 残りは、このインデックスを使用して要素を@I並べ替えることです。@F
  3. 二重引用符で配列を割り当てると、要素はスペースで区切られた文字列に変換されます。
  4. -p$_コンテンツの自動印刷を可能にするPerlのオプションを追加する-l必要がありますnewline

答え3

Perl モジュールの使用 Sort::Naturally

入力データ

ID M2 M5 M8 M1 M3 M9 M700000
A1 m1,2 m1,5 m1,8 m1,1 m1,3 m1,9 m1,7000000
A2 m2,2 m2,5 m2,8 m2,1 m2,3 m2,9 m2,7000000
A3 m3,2 m3,5 m3,8 m3,1 m3,3 m3,9 m3,7000000
A1000 m1000,2 m1000,5 m1000,8 m1000,1 m1000,3 m1000,9 m1000,7000000
perl -MSort::Naturally -lane '
  if ($. == 1) {
    @indices = (0, map  { $_->[0] }
                   sort { ncmp($a->[1], $b->[1]) }
                   map  { [$_, $F[$_]] }
                   1..$#F
               );
    $, = " ";
  }
  print @F[@indices]
' test.data

出力

ID M1 M2 M3 M5 M8 M9 M700000
A1 m1,1 m1,2 m1,3 m1,5 m1,8 m1,9 m1,7000000
A2 m2,1 m2,2 m2,3 m2,5 m2,8 m2,9 m2,7000000
A3 m3,1 m3,2 m3,3 m3,5 m3,8 m3,9 m3,7000000
A1000 m1000,1 m1000,2 m1000,3 m1000,5 m1000,8 m1000,9 m1000,7000000

答え4

GNUがある場合は、awk次のことを試すことができます:

NR == 1 {
    for (i = 2; i <= NF; i++) {
        columns[substr($i, 2)] = i;
    }
    count = asorti(columns, sorted, "@ind_num_asc");
    printf("%s", $1);
    for (i = 1; i <= count; i++) {
        printf(" M%s", sorted[i]);
        indx[i] = columns[sorted[i]];
    }
    print "";
    next;
}
{
    printf("%s", $1);
    for (i = 1; i <= count; i++) {
        printf(" %s", $(indx[i]));
    }
    print "";
}

関連情報