1

複数の列でデータを並べ替えることについて質問があります。私は間違いなくこれの初心者であり、最初の列の順序を失うことなく、どのようにして1つの列で並べ替え、次に別の列で並べ替えることができるのか疑問に思っています。3つの列で構成されるタブ区切りデータのファイルがあります。データの大部分はペアになっていない(1つのID、最初の列、および位置の開始と終了、2番目と3番目の列)。ただし、同じID(最初の列)に複数のエントリがある場合があります。これらはグループ化されたままである必要があります(別のIDがない限り、次のエントリからスペースを離さずに)。データは実際には最初の列に関して既に並べ替えられていますが、元の並べ替えを維持しながら、開始位置(2番目の列)に基づいて数値で並べ替える必要があります。このような:

現在の形式:

PITG_00129  606 1436

PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 4464 11708
PITG_00133 1 2946
PITG_00133 4081 4515

必要な形式:

PITG_00129  606 1436

PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 1 2946
PITG_00133 4081 4515
PITG_00133 4464 11708
4

6 に答える 6

5

これはPythonで非常に簡単に行うことができます。まず、適切な形式でデータを読み取る必要があります。

def line_to_tuple(line):
    data = line.split()
    return (data[0],int(data[1]),int(data[2]))

これにより、各行がタプルに変換され、辞書式順序で並べ替えられます。文字列(最初の列)は簡単に並べ替えることができるので、心配する必要はありません。2番目と3番目の列は、正しくソートするために整数に変換する必要があります。

with open(inputfile) as fin, open(outputfile,'w') as fout:
    non_blank_lines = (line for line in fin if line.strip())
    sorted_lines = sorted(non_blank_lines,key=line_to_tuple)
    fout.writelines(sorted_lines)

フィールド間の空白行を保持するための別の実装を次に示します。

import itertools
def field1(line):
    data = line.split()
    try:
        return data[0]
    except IndexError:
        return None

def fields(line):
    data = line.split()
    return data[0],int(data[1]),int(data[2])

with open('test.dat') as fin, open('output.dat','w') as fout:
    for k,v in itertools.groupby(fin,key=field1):
        if k is None:
            fout.write('\n')
        else:
            fout.writelines(sorted(v,key=fields))

これは、itertoolsを使用して空の行に基づいてファイルをチャンク化し、それらのグループを個別にソートしてから書き戻します。

出力は次のとおりです。

temp $ cat output.dat 
PITG_00129  606 1436

PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 1 2946
PITG_00133 4081 4515
PITG_00133 4464 11708
于 2013-01-15T21:29:45.160 に答える
3

これはperlでは非常に簡単であり、常にperlであるTIMTOWDIを使用します(これを行う方法は複数あります)。以下の2つの例では、同等の結果が得られます。

オプション1-ソートでor比較演算子を使用します。この例には、オブジェクトの配列があります。最初にlast_nameでソートし、等しい場合はfirst_nameをチェックします。これは、さまざまな変数によってデータを何度も再利用する予定がない場合に適しています。

my @records = (...);

my @sorted = sort { $a->last_name cmp $b->last_name ||
                    $a->first_name cmp $b->first_name } @records;

オプション2-ソートプラグマを使用します。Perlのソートはデフォルトでは安定していませんが、ソートプラグマを使用して安定させることができます。これは、同じデータを異なる変数で複数回再利用し、最後の並べ替えからの順序をそのまま維持したい場合に適したオプションです。

use sort 'stable';

@records = sort { $a->first_name cmp $b->first_name } @records;

@records = sort { $a->last_name cmp $b->last_name } @records;
于 2013-01-15T22:48:00.850 に答える
2

次々にソートを実行し、ソートが安定している場合、最初のソートの順序は、2番目のソートの等しいキーに対して保持されます。Pythonのsort関数は安定していると思いますが、Perlについてはよくわかりません。

于 2013-01-15T21:28:52.917 に答える
1

カンマ区切りの値のリストを最初の列で並べ替え、次に2番目の列で並べ替えるには、次のようなコマンドを実行します。

csvfix sort -f 1,2 data.csv

http://csvfix.byethost5.com/csvfix15/csvfix.html

まず、タブを見つけてカンマに置き換える必要があります。

于 2013-01-15T21:31:40.803 に答える
1

アルゴリズム

 1.  Get the unique first column values
 2.  for each first column value grep the origiginal file and redirect to temp file
       you will get the partial output in temp file for each unique value.  you can use sort command to sort by 2nd column on the temp file and redirect the output (append) to output file. 
于 2013-01-15T21:32:48.090 に答える
1

これは、シュワルツ変換を使用してクラスター化された行を最初の数値でソートするPerlオプションです。トランスフォームは、簡単に並べ替えることができるキーで並べ替えられるものにタグを付けます。この例では、mapすべての行にタグを付けています。次に、sortブロックは、これらのタグ付けされた値がどのようにソートされるかを指定します:2番目の要素によって。次に、タグなしの値がprint編集されます。

use strict;
use warnings;

local $/ = ''; #paragraph mode

while (<>) {
    print $_->[0], "\n"
      for sort { $a->[1] <=> $b->[1] }
          map  { [ $_, (split)[1] ] }
               split /\n/;

    print "\n";
}

呼び出し:$ perl script.pl data.txt > data_sorted.txt

ワンライナーとして(perl 5.10以降):

perl -nE'BEGIN{$/=""}say$$_[0]for sort{$$a[1]<=>$$b[1]}map[$_,(split)[1]],split/\n/;say""' data.txt >data_sorted.txt

data.txt:

PITG_00129  606 1436

PITG_00130  417   987
PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 4464 11708
PITG_00133 1 2946
PITG_00133 4081 4515

PITG_00134 446 1170
PITG_00134 41 294
PITG_00134 17 451

data_sorted.txt:

PITG_00129  606 1436

PITG_00130  1   987
PITG_00130  417   987

PITG_00132  2   1321

PITG_00133 1 2946
PITG_00133 4081 4515
PITG_00133 4464 11708

PITG_00134 17 451
PITG_00134 41 294
PITG_00134 446 1170
于 2013-01-15T22:47:35.303 に答える