0

次のようなデータセットがあります

1.データセット

NR_046018   DDX11L1 ,   0   0   1   1   1   1   1   1   1      1    0   0   0   0   1.44    2.72    3.84    4.92
NR_047520   LOC643837   ,   3   2.2 0.2 0   0   0.28    1   1   1   1   2.2 4.8 5   5.32    5   5   5   5   3
NM_001005484    OR4F5   ,   2   2   2   1.68    1   0.48    0   0.92    1   1.8 2   2   2   2.04    3.88    3
NR_028327   LOC100133331    ,   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

2. 必要なもの

  1. 配列を 10 回シャッフルします。シャッフルの後、配列を 2 つの新しい配列、たとえばset1set2に分割します。(半分はset1に入り、残りの半分はset2に入ります)

  2. 新しい各配列から、数値の各行の最大値を計算し、その後にすべての行の平均最大値を計算します。

  3. set1およびset2の 10 個の平均最大値を取得します。(10 回のシャッフルに対して 10 個の平均最大値)セットに対して取得された 10 個の平均最大値の平均を計算します。これを10avg1および10avg2と呼びましょう。

  4. 1000 10avg2と 1000 10avg2のリストを取得します。

3.コード

use warnings;
use List::Util qw(max shuffle);

my $file = 'mergesmall.txt';

#Open file and output file
open my $fh,'<',$file or die "Unable to open file";
open OUT,">Shuffle.out" or die;

#Read into array
my @arr = <$fh>;

#Intialize loop for shuffling 10 times
my $i=10;
while($i){
    my @arr1 = ();  #Intitialize 1st set
    my @arr2 = ();  #Initialize 2nd set

    my @shuffled = shuffle(@arr);

    push @arr1,(@shuffled[0..1]); #Shift into 1st set
    push @arr2,(@shuffled[2..3]); #Shift into 2nd set



    foreach $_(@arr1){
        my @val1 = split;
        my $max1 = max(@val1[3..$#val1]);

         $total1 += $max1;
         $num1++;
    }

    my $average_max1 = $total1 /  $num1;
    #print "\n\n","Average max 1st set is : ",$average_max1;
    print OUT "Average max 1st set is : ",$average_max1;

        foreach $_(@arr2){
        my @val2 = split;
        my $max2 = max(@val2[3..$#val2]);

        print "\n\n";

         $total2 += $max2;
         $num2++;
    }

    my $average_max2 =  $total2 /  $num2;
    #print "\n\n","Average max 2nd set is : ",$average_max2;
    print OUT "\n","Average max 2nd set is : ",$average_max2,"\n\n";


    $i--;

}       

4. 問題

これまでに記述できたコードは、各set1およびset2の最大 10 個の平均を取得できます。これら 10 個の最大平均の平均を計算する方法がわかりません。これがわかれば、forループを 1000 回実行して 1000 10avgset1と 1000 10avgset2を簡単に取得できます。

5. 注意事項

  1. 実際のデータセットには、最大 400 の数字で構成される各行があり、それより少ない行もあれば、まったくない行もありますが、400 を超えることはありません。

2.実際のデータセットには 41,382 行あります。Set1 は 23,558 行で構成され、set2 は 17,824 行で構成されます。

3.ファイルは .txt ファイルで、各行のすべての数字はタブで区切られています。

最大平均の平均を計算する方法について、いくつかのアイデアを提供できれば幸いです。使おうと思ったのpush @10avgset1, $average_max1ですが、なかなか使えません。

4

1 に答える 1

2

私が最初に指摘したこと:あなたはstrictプラグマを使用しておらず、実際にはグローバル変数を使用しています。それがあなたが望むものかどうかはわかりません。また、変数名は数字で始まらない場合があります(一般的に)。

私が注意した2番目のこと:あなたは自分自身をかなり繰り返します。

これは、この奇妙な「最大値の平均化」を行う関数です。

use constant CARRY => 1; # set behaviour of original code;

sub make_accumulator {
    my $group = shift;
    my ($max, $num) = (0, 0) if CARRY;
    my @acc;
    my $acc = sub {
        my ($max, $num) = (0, 0) unless CARRY;
        for (@_) {
            $max += max @$_;
            $num++;
        }
        my $avg = $max / $num;
        push @acc, $avg;
        printf "Average max in set %d is %.2f\n", $group, $avg;
        $avg;
    };
    my $get = sub { @acc };
    ($acc, $get);
}

次に、を実行できますmy ($acc, $get) = make_accumulator(1)。ここで、$accはアルゴリズムをカプセル化するコールバックであり、$getこれまでに計算されたそのようなすべての値の配列を返します。

実際の平均は次のように計算されます

sub average { sum(@_) / @_ }

スクリプトを初期化するために、私は

#!/usr/bin/perl

use strict;
use warnings;
use List::Util qw(shuffle max sum);

use constant CARRY => 1;

my @arr = map {my @arr = split; [@arr[3..$#arr]]} <DATA>;

my ($acc1, $get1) = make_accumulator(1);
my ($acc2, $get2) = make_accumulator(2);

@arrの行は、ロード中に1回だけ行を解析します。@arr次に、シャッフルされたバージョンの:を数回ループします。

for (1 .. 5){
    my @shuffled = shuffle @arr;

    my $halfway = int (@shuffled / 2);
    my @arr1 = @shuffled[0 .. $halfway];
    my @arr2 = @shuffled[$halfway .. $#shuffled];

    my $average_max1 = $acc1->(@arr1);
    my $average_max2 = $acc2->(@arr2);

    printf "running: %.2f %.2f\n", average($get1->()), average($get2->());
    print "\n";
}

ここでは、シャッフルされたリストを厳密に半分に分割しました23557。後でハードコーディングする必要があります。次に、set1とset2の移動平均を出力します。

これにより、次のような出力が生成されます。

Average max in set 1 is 2.93
Average max in set 2 is 4.60
running: 2.93 4.60

Average max in set 1 is 3.17
Average max in set 2 is 4.60
running: 3.05 4.60

Average max in set 1 is 3.09
Average max in set 2 is 4.60
mrunning: 3.07 4.60

Average max in set 1 is 3.17
Average max in set 2 is 4.55
running: 3.09 4.59

Average max in set 1 is 3.22
Average max in set 2 is 4.03
running: 3.12 4.48

CARRYfalse値に設定すると、次のようになります。

Average max in set 1 is 3.07
Average max in set 2 is 5.12
running: 3.07 5.12

Average max in set 1 is 3.07
Average max in set 2 is 2.46
running: 3.07 3.79

Average max in set 1 is 3.07
Average max in set 2 is 4.40
running: 3.07 3.99

Average max in set 1 is 3.41
Average max in set 2 is 4.40
running: 3.15 4.10

Average max in set 1 is 3.07
Average max in set 2 is 5.12
running: 3.14 4.30

4行の可能な組み合わせは非常に少ないので、これはばかげているように見えます(n!/(n/2)!、私は推測します)。

もちろん、これらの値は実行されるたびに異なります。これshuffleは、すでに疑似ランダムであるためです。

編集:

DATAファイルハンドルは、スクリプトの最後に次のようなデータセクションがあることを前提としています。

__DATA__
NR_046018   DDX11L1 ,   0   0   1   1   1   1   1   1   1      1    0   0   0   0   1.44    2.72    3.84    4.92
NR_047520   LOC643837   ,   3   2.2 0.2 0   0   0.28    1   1   1   1   2.2 4.8 5   5.32    5   5   5   5   3
NM_001005484    OR4F5   ,   2   2   2   1.68    1   0.48    0   0.92    1   1.8 2   2   2   2.04    3.88    3
NR_028327   LOC100133331    ,   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

コマンドラインにリストされているファイルを使用するには、次の手順を実行します。

my @arr = map {...} <>;  # no explicit filehandle

または手動でファイルを開きます。

于 2012-12-21T10:56:55.340 に答える