2017-11-21 19 views
1

データセットtypes100 rows x 61 columnsです。最初の列はType_IDを示し、残りの60列は期間に関連しています。別のデータセットからのSAS多次元配列の初期化

別のデータステップでcalculate;私はtypesの100行と60列のデータで初期化された多次元配列timeType{100,60}を作成したいと思います。

私がこれまでに読んだことのあるすべてのSASドキュメントは、明示的な列参照を使用して多次元配列を初期化し、列は配列の次元に適合するように強制します。

データセットをアレイに効率よく読み込むにはどうすればよいですか?

+0

60桁の数値はすべて数字ですか?たとえば、3行5列のサンプルデータを投稿するとよいでしょう。 – Quentin

+1

6,000個の変数をすべて配列にロードする理由を教えてください。これは一時的な配列ですか、それともデータセットに格納する予定ですか?ここのユースケースは何ですか?非常に一般的なデータ構造でも、SASで非常に使いやすいものでもない2次元配列よりも、物事を扱う別の方法があるかもしれません。 – Joe

+0

私はいくつかの金額にわたって60の割引率を適用しています。私は現在4種類のディスカウントタイプを持っていますが、それを解決するためのコードを書いていますが、異なるディスカウントタイプと_m_異なるディスカウント期間で一般化する方法を考えることができませんでした。 私は100K以上の金額を持っています。現在価値の計算は、トランザクションのさまざまなコンポーネントに対して複数回実行する必要があります(私は、さまざまなトランザクションコンポーネントを処理する自己生成コードを使用しています)思い出がもっと効率的になるだろう。 – candlejack

答えて

1

私は配列では大きすぎず、以下はスタイルポイントを獲得できませんが、それはスタートです。

基本的なアプローチは、すべてのデータを2次元配列に読み込むためにDoWループを使用することです。

data have; 
    do TypeID=1 to 5; 
    p1=10*TypeID; 
    p2=100*TypeID; 
    p3=1000*TypeID; 
    output; 
    end; 
run; 

data _null_; 
    *DOW loop to read data into array; 
    do until (last); 
    set have end=last; 

    array timeType(5,3) _temporary_; 
    array p{*} p:; 

    row++1; 
    do col=1 to dim(p); 
     timeType{row,col}=p{col}; 
    end; 
    end; 

    *PUT the values of the array to the log, for checking; 
    do i=1 to dim1(timeType); 
    do j=1 to dim2(timeType); 
     put timeType{i,j}=; 
    end; 
    end; 

    drop row col i j; 
run; 
2

クエンチンと非常に似ています。私はDorfmanを有名なコンストラクタを読取りループに使用しました。

data types; 
    do type_id = 1 to 100; 
    array x x1-x60; 
    do over x; global_counter+1; x = global_counter; end; 
    output; 
    end; 
run; 

data calculate(keep=testid result) typesread_check(keep=x1-x60); 

    array matrix(100,60) _temporary_; 

    * load matrix; 
    do _n_ = 1 by 1 until (end); 
    set types end=end; 
    array x x1-x60; * this array is composed of variables that are filled by the SET operation; 
    do _i_ = 1 to dim(x); 
     matrix(_n_,_i_) = x(_i_); 
    end; 
    end; 

    * unload matrix to check load with COMPARE; 
    * can be commented out/removed after confidence established; 
    do _n_ = 1 to 100; 
    do _i_ = 1 to 60; 
     x(_i_) = matrix(_n_,_i_); 
    end; 
    output typesread_check; 
    end; 

    * perform computations that output; 
    testid = 1; 
    result = sum(of matrix(*)); 

    output calculate; 
run; 

* output is zero rows of differences. That means the matrix was populated correctly; 
proc compare noprint data=types(drop=type_id) compare=typesread_check out=diff outnoequal; 
run; 

あなたが_temporary_オプションを削除するタイプのデータに沿って計算結果を保持する場合。 keep (testid result matrix:)行列(100,60)に対応する6,000の追加の列を持つ出力を取得する

0

代わりにHASHオブジェクトを使用します。最初に、「行列」ではなく通常のデータセットにレートを転記します。または、元々そのように作成してください。

data rates; 
    do type=1 to 3 ; 
    do time=1 to 3 ; 
     input rate @@ ; 
     output; 
    end; 
    end; 
cards; 
.1 .2 .3 .4 .5 .6 .7 .8 .9 
; 

ここでは、データの例を示します。私は、レートテーブルのレコードと一致しないレコードを1つ含んでいました。

data have ; 
    input type time amount expected; 
cards; 
1 2 100 20 
2 3 100 60 
4 5 100 . 
; 

次にHASHオブジェクトに速度をロードし、現在の型および時間の組み合わせのためのレートを見つけるために.FIND()メソッドを使用します。

data want ; 
    set have ; 
    if _N_ = 1 then do; 
    declare hash h(dataset:"rates"); 
    rc = h.defineKey('type','time'); 
    rc = h.defineData('rate'); 
    rc = h.defineDone(); 
    call missing(rate); 
    drop rc; 
    end; 
    if (0=h.find()) then payment=amount*rate; 
run; 

結果。

Obs type time amount expected payment rate 

1  1  2  100  20   20  0.2 
2  2  3  100  60   60  0.6 
3  4  5  100   .   .  . 
関連する問題