2015年12月16日水曜日

SAS Enterprise Guide(EG)でプロンプト(マクロ変数)を使う

ここ最近のお仕事で、SAS Enterprise Guide(EG)での開発が多いのですが、マクロ変数をGUIで設定できないものかと思う時があります。例えばお客様用にプロセスを開発する場合、期間抽出の条件を任意にしたいというご要望がある場合などです。プロンプトはそんな時に効果を発揮します。

結論から言うと、プログラム的にはマクロ変数と同じですが、プロセスフロー実行時に以下のようなウィンドウが出て、値を定義するように求められます。


これなら、値の設定を失念することもなくなりますし、お客様にEGPを提供する場合も負担が少なくてすみます。以下では期間抽出をプロンプトで行う方法を例に、プロンプトの定義方法をご紹介します。

以下のようなデータセットから、任意の年月の範囲をプロンプトで指定して、レコードを抽出してみましょう。



①クエリビルダからプロンプトマネージャを選択

 クエリビルダを開くと、プロンプトマネージャの項目があります。プロンプトマネージャを選択し、追加をクリックします。すると、プロンプト作成のウィンドウが出てきます。




プロンプトマネージャをクリック



追加を選択すると、プロンプトの作成画面が現れます。


②プロンプトの作成

 名前はわかりやすいものにしましょう。今回は年月を範囲指定して抽出するためのプロンプトを作成します。開始年月をSTART_YM、終了年月をEND_YMで作成します。

プロンプトにNULLを設定できないようにするには、「空白以外の値が必要」にチェックを入れます。



  「プロンプトの種類と値」のタブに移動すると、プロンプトの詳細定義が行えます。今回は数値変数に対する抽出を行う目的なので、「プロンプトの種類」は数値を選択します。また小数点以下は使用しないため、「整数値のみ許可する」にチェックを入れます。

最後に「最小値」、「最大値」を入力すれば、プロンプトの作成が完了します。


同様の手順でEND_YMも作成します。


③抽出条件にプロンプトを設定

 では、早速クエリビルダの抽出条件にプロンプトを使用してみましょう。変数「ym」に対して、演算子を「範囲内の値」します。
赤枠の部分をクリックすると、下記のようなウィンドウが表示されます。ウィンドウ内の「プロンプト」タブを選択すると、先ほど作成したプロンプトの一覧が表示されますので、「開始値」には「START_YM」、「終了値」には「END_YM」を選択します。

「開始値」、「終了値」の欄に直接「&START_YM」、「&END_YM」と直接入力しても構いません。




プログラムのプレビューを見ると、プロンプトが「&START_YM」、「&END_YM」になっており、内部的にはマクロ変数と同じ扱いになっていることがわかります。

では、クエリを実行しましょう。冒頭でご紹介した画面が出たので、値を入力します。2010年4月から2011年3月までのレコードを抽出してみましょう。

以下が実行結果です。

うまく抽出できています。
ちなみに、②でプロンプトにはNULL値を除外しているので、NULLを設定すると以下のようなエラーメッセージが表示されます。

後続の処理でプロンプトを使用する場合は以下の場所にチェックをいれましょう。




これによりプロセスフロー内で、プロンプトがマクロ変数として参照できるようになります。


2015年11月5日木曜日

【求人情報】 2016年1月入社 SASエンジニア


                                       
本日は『津波防災の日』です。
http://tsunamibousai.jp/

東日本大震災から4年。
時の経過とともに、日常を取り戻すことができている人も多い反面、
まだまだ困難な状況の中、必死にがんばっている人もたくさんいます。
『皆さまに心からの笑顔が1日も早く戻りますように。』




さて、ネイチャーインサイトでは、2015年 第3弾の求人募集をスタートしました。

ビッグデータ市場は、2019年までの予測で、年平均成長率27%のペースで拡大し、1469億円に上るともいわれております。

一方、企業の課題として、
 ・データ分析、統計解析のスキルを持った人材の不足
 ・予算準備が不十分
などが上げられております。

つまり、益々成長が見込まれる分野で、人材不足が懸念されているということ!


当社でSASエンジニア・データサイエンティストを目指しませんか!!
ご興味ある方は、DODA求人広告(下記のリンク)をご覧ください。


未経験からはじめる SASエンジニア


皆さまのご応募をお待ちしております。


2015年10月19日月曜日

SAS での回帰不連続デザイン (RDD) とビジネスでの応用について

2011年の米南東部 SAS ユーザー会 (SESUG) 発表資料で政策の効果を推定するための回帰不連続デザイン (RDD)を実行するマクロが紹介されている発表 Schoeneberger (2011) "RDPLOT: A SAS® MACRO for Generating Regression Discontinuity Plots" を見つけたので、
  1. RDD マクロの解説
  2. RDD そのものの解説
  3. ビジネスでの応用
をあわせて紹介したいと思います。かなりマニアックなテーマなので、「SAS にこじつけて自分の趣味の話をしたいだけだろ」と思われるかも知れません。おおむねその通りですがどうかご容赦ください。

RDDとは?

回帰不連続デザイン (RDD, Regression Discontinuity Design) というのは回帰分析の一種で、初め Thistlethwaite & Campbell (1960) "Regression-discontinuity analysis: An alternative to the ex post facto experiment" で発表されたものです。社会科学の研究では割りとポピュラーな手法ですが、日本語での情報はあまりありません。そのため, RDD の和訳も定着しておらず、切断回帰デザインとか非連続回帰計画というふうに呼ばれることもあります。例えば日本語ですと
  • アングリスト&ピスケ (2013) 『ほとんど無害な計量経済学 –応用経済学のための実証分析ガイド–』, 大森義明・田中隆一・野口晴子・小原美紀訳, NTT出版. 原著: Angrist, Joshua D. and Jrn-Steffen Pischke (2008) “Mostly Harmless Econometrics: An Empiricist’s companion,” Princeton University Press
  • 津川友介 (2015) 『回帰分断デザインRegression discontinuity design(および分割時系列デザイン)|医療政策学×医療経済学
  • 森田果 (2014) 『実証分析入門 –データから「因果関係」を読み解く作法–』, 日本評論社
などで RDD が言及されています。より専門的な解説をした英語の論文は末尾の参考文献に挙げておきます。私は学生時代に、教育政策の効果を検証する方法として学びました。では、ビジネスの文脈、例えばマーケティングなどに応用されてはいないかと調べたところ、 Marketing Science 誌に掲載された論文で、RDD をマーケティング全般へ応用する方法について論じた Hartmann, Nair, & Narayanan (2011) "Identifying Causal Marketing Mix Effects Using a Regression Discontinuity Design" を見つけました。
上記の文献を読むだけでもなにを意図したものかおおむねわかるかと思いますが、この Hartmann らの論文に沿って簡単に解説したいと思います。
まず、ある政策を実施して、その効果がどれだけあったかを知りたいとします。 民間企業の立場なら、顧客に対するプロモーションを実施して、どの程度売上につながったか、とも解釈できます。どちらの想定でも、何らかの成果を期待してコストを払って施策を行っているわけなので、実際に効果があがっているかの検証は大事です。Hartmann et al. (2011) では、カジノでは少数の上客 (ハイローラー) が大きな利益をもたらしてくれることから、ハイローラーに対する優遇サービスを例に挙げていますが、 他の業種でのプロモーションの施策に置き換えて考えても問題ありません。単純に考えると、ハイローラーに対し優遇サービスを実施し、それ以外の利用客には実施しないとすると、
(効果) = (優遇を受けた利用客の平均) - (優遇を受けなかった利用客の平均)
というふうに優遇を受けた利用客と受けなかった利用客で分割し、それぞれのグループについて1人あたり売上額などを計算し、さらにその差をとれば、効果の大きさとみなせそうです。視覚的にあらわすならば、以下の図1のような棒グラフで表せます。
図1: 施策の有無と1人あたり売上額の差

ところが、実際は効果の大きさを正しく見積もるのは容易ではありません。2つのグループの利用客の傾向がかたよるからです。そもそも、カジノ側は、最初から多く遊んでくれるハイローラーに対してのみ優遇します。そのためハイローラーは、仮に施策を受けなかったとしても多く遊ぶ可能性が高いのです。逆に優遇を受けなかったグループは、優遇を受けたとしても商品を購入する可能性が比較的低いかもしれません。よって、ここで計算した差は、純粋な施策の効果だけでなく、偏った平均によるバイアスも含まれてしまい、過大に見積もってしまいます。同様の理屈で、逆にあまり遊ばない利用客に対して重点的に優遇を行った場合、効果が過少評価されるでしょう。
医薬品の臨床実験や、農作物の品種試験でも、薬品を投与した場合・しない場合や、新しい品種・既存の品種を比較して性能の差を見るのですが、このような偏りが起こらないようにコントロールするのが普通です (いわゆるランダム化)。 しかし、マーケティングに関しては利益に直結するため必ずしもこのコントロールができるとは限りません。
このように、偏りがある場合の対処方法として考案された方法が RDD です。 特に、この施策を受けるか受けないかの判断基準がしきい値 (これをカットオフ点ともいいます) で表現されるとき RDD が利用可能です。 ある数値を超えた人間が施策を受け、超えなかった人間は施策を受けないとします。
カジノの例でいうならば、利用客ごとの1日にカジノで使う金額を見て、一定額以上ならハイローラーに分類し、優待サービスを実施します。事実、ハイローラーに分類された利用客は1日あたりの使用金額が非常に多く、かつ来場回数も増えることが確認されています。利用客のハイローラーへの分類の前と後の利用金額の関係を擬似的に表すと、以下の図2のようになります。
図2: RDDの視覚的な説明

実際に効果があるのなら、中央のカットオフ点を境に、直線が断層のようにずれるはずです。この直線の、不連続な地点の上下のずれの大きさが、施策による効果の大きさとみなせます。
ここで、このカットオフ点の前後、たとえば前後1万円とすると、ハイローラーに分類されるかどうかに関係なく、適用前の利用客の使用金額にほとんど違いがありません。よって、この限られた範囲ならば、先に述べた偏りがほとんどないと考えられます。ここから、データから狭い範囲に属する利用客の情報だけを取り出して分析すれば、効果の大きさをうまく見積もることができる、というのが RDD の基本理念です。RDD は回帰分析を応用することでこのずれの大きさを計算し、そこから効果の大きさを推定します。

SAS での実行方法

冒頭で紹介した Schoeneberger (2011) で、 SAS マクロのすべてが公開されています。これは SAS/STAT SAS/GRAPH があれば実行可能なのでたいていの環境で実行できるのですが、 SAS University Edition では SAS/GRAPH がないため gplot プロシジャが使用できません。 そこで、 sgplot プロシジャで でグラフを描画するように書き換えたコードを使用します。このプログラムは記事の末尾に掲載しておきます。 元の regdis マクロはインプットデータを物理名で参照しますが、このままだと使い勝手が悪いので、 そのまま使う場合でも、元のプログラムも9ページ右上の最初のデータステップの
set "%bquote(&path)%bquote(&data_in)";
のところを
set &data_in;
に変えたほうが使いやすいと思います。
次に、以下のコードでインプットデータを作成します。
/*------------------------------
 RDD デモコード
 SAS/STAT が必要
-------------------------------*/

data param;
input _TYPE_$ _NAME_$ x_prior x_post;
cards;
COV x_prior 2 1 
COV x_post  1 3
;
run;

proc simnormal seed=1 numreal=100 data=param(type=cov) out=sample ;
    var x_prior x_post;
run;

data sample;
    call streaminit(1);
    set sample;
    x_prior+10;
    x_post +10;
    is_high=0;
    if x_prior >10 then do;
        x_post+rand('normal',4,.5);
        is_high=1;
    end;
run;
simnormal プロシジャというのは、与えられたパラメータから乱数を生成するプロシジャで、 SAS/STAT があれば使用可能です。これで2次元正規乱数を生成し、さらに加工することで擬似データを作成しています。乱数の種を固定しているので、毎回同じ結果になるはずです。データは各レコードが利用客の1人分の記録を表し、変数の x_prior が施策前の利用客の使用金額、 x_post が施策後の金額、 is_high が適用対象かどうかを表す変数です。
このデータを regdis マクロに入力します。私がデータセットの1行だけ改変したものですと、
%regdis(%str(),work.sample,x_prior,x_post,is_high,10,above,Y);
後で掲載する University Edition 対応版ですと
%regdis(work.sample,x_prior,x_post,is_high,10,above,Y);
を実行してください。以下は引数の解説です。
  1. path : ファイルのあるフォルダパスです。UniversityEdition版は廃止したため、次の data_in が第一引数になります。
  2. data_in: データセットのファイル名です。マクロを改変したので今回はデータセット名を書いています。
  3. pretest: 施策前の状態を表す変数です。X軸に当たります。
  4. posttest: 施策後の状態を表す変数です。Y軸に当たります。
  5. group: 各個人に対して施策がなされたかどうかの数値変数。適用対象なら 1、そうでなければ 0 です。
  6. cutscore: 適用対象を決めるしきい値 (カットオフ点)。今回は 10 とします。
  7. treat_loc: カットオフ点のどちら側が施策適用対象か。今回は 10 を越える利用客が対象なので、 above と入力します。逆は below です。
  8. plot_data: グラフにレコードの散布図を描くかどうか。 Y/N どちらかを入力します。 基本的に Y のほうが良いでしょう。
これを実施すると、 glm プロシジャで直線の傾きと切片が推定されるほか、結果のグラフが以下の図3のように表示されます (SAS University Edition の場合、使用しているスタイルによって結果が若干変わります)。
図3: 施策前後の使用金額の散布図と RDD による回帰直線の当てはめ

このマクロでは、直線回帰のみですが、仮説検定から2つのグループでそれぞれ傾きが異なると判定されたため、それぞれで傾きが異なっています。入力データによっては、両者の傾きが同じになる場合もあります。実際に RDD を使用する場合には、他のモデルと比較したり、使用するデータの範囲を決めたりといったことが必要です。

応用の可能性

Hartmann et al. (2011) ではさらに、いろいろな分野での応用の可能性を指摘しています. Table 6. にその一覧表があるので、和訳したものを掲載します。ここでのスコア変数というのは、上記のグラフの横軸に対応する変数です。一般には RDD は縦と横で異なる変数をとることができます。いずれの場合でも、スコア変数があるカットオフ点を超えた時に施策が行われるという例を示しているので、 RDD のフレームワークを用いて施策の有無と結果変数の差を見ることで、施策の効果の大きさがわかるということです。

SAS University Edition 対応版マクロ

/*---------------------------------------------------------------------
RDPlot macro program modified to use it in SAS University Edition
S-Katagiri, Nature Insight co., 24/Jun/2015
http://blog.n-insight.co.jp/

The original macro program is from
Schoeneberger, J. A. (2011).
RDPLOT: A SASR Macro for Generating Regression Discontinuity Plots. 
Proceedings of the annual Southeastern SAS Users Group Conference.
http://analytics.ncsu.edu/?page_id=3375
---------------------------------------------------------------------*/

**assumes data_in file is one line per unit-of-analysis record;
**assumes group is dichotomous, numeric variable coded 0=control, 1=treatment;
*data_in=the SAS dataset name for analysis;
*pretest=the pre-test score by which a cut-score being applied creates treatment-control groups;
*posttest=the posttest, dependent variable of interest;
*group=variable denoting treatment (1) or control (0) group membership;
*cutscore=numeric value on the pre-test that serves as the cut-score;
*treat_loc=denotes whether the treatment is above or below cut-score: insert 'above' or 'below' for this value;
*plot_data=denotes whether the user wants to plot actual data 'Y' or just RD lines 'N';

%macro regdis(data_in,pretest,posttest,group,cutscore,treat_loc,plotdata);
    data regdis;
        set &data_in.;
        ** homogeneity の検定のために相互効果の変数作成;
        interact=&group*&pretest;
    run;
    ** x, yの最小値最大値をマクロ変数に取得;
    proc sql noprint;
        select min(&pretest), max(&pretest), min(&posttest),
        max(&posttest)
        into: x_min, : x_max, : y_min, : y_max
        from regdis;
    quit;
    ** teart_loc に応じて補間点を並べる;
    %if "%upcase(&treat_loc)"="BELOW" %then %do;
        %let x_0=&x_max;
        %let x_1=&x_min;
    %end;
    %if "%upcase(&treat_loc)"="ABOVE" %then %do;
        %let x_0=&x_min;
        %let x_1=&x_max;
    %end;
    ** glmによる相互作用テスト (homogeneity assumption);
    ods output parameterestimates=paramsint;
    proc glm data=regdis namelen=32;
        model &posttest=&group interact &pretest/ss1
        solution;
        run;
    quit;
    ** homogeneity なら傾きを一定とする。そうでないなら個別に傾きを計算;
    data paramsint;
        set paramsint;
        if (parameter="interact") and (probt gt .05) then
            call symput('hetero','N');
        if (parameter="interact") and (probt le .05) then
            call symput('hetero','Y');
    run;
    ** 以下は傾き一定の場合 (hetero='N');
    %if "&hetero"="N" %then %do;
        ** 傾きを計算。;
        ods output parameterestimates=params;
        proc glm data=regdis namelen=32;
            model &posttest=&group &pretest/ss1 solution;
            run;
        quit;
        ** パラメータをマクロ変数に取得;
        proc sql noprint;
            select estimate into: intercept_g0
            from params
            where parameter="Intercept";
            select estimate into: grp_slp
            from params
            where parameter=lowcase("&group");
            select estimate into: cut_slp_g0
            from params
            where parameter=lowcase("&pretest");
        quit;
        %let intercept_g1=%sysevalf(&intercept_g0+&grp_slp);
        %let cut_slp_g1  =&cut_slp_g0;

    %end;
    ** 以下 homogeneity ではない場合 (hetero='Y');
    %if "&hetero"="Y" %then %do;
        ** 以下の glm で2つのグループの回帰係数を別々に推定;
        ods output parameterestimates=paramsg1;
        ** treatment グループの係数;
        proc glm data=regdis;
            model &posttest=&pretest/ss1 solution;
            where (&group=1);
            run;
            quit;
        ods output parameterestimates=paramsg0;
        ** control グループの係数;
        proc glm data=regdis;
            model &posttest=&pretest/ss1 solution;
            where (&group=0);
            run;
        quit;
        ** sql プロシジャでパラメータを取得;
        proc sql noprint;
            select estimate into: intercept_g1
            from paramsg1
            where parameter="Intercept";
            select estimate into: cut_slp_g1
            from paramsg1
            where parameter=lowcase("&pretest");
            select estimate into: intercept_g0
            from paramsg0
            where parameter="Intercept";
            select estimate into: cut_slp_g0
            from paramsg0
            where parameter=lowcase("&pretest");
        quit;
    %end;
    ** 以下、共通処理;

    ** 回帰直線の点を追加;
    data regdis2;
        set regdis end=eof;
        output;
        if eof then do;
            %do i=0% to 1;
                x=&&x_&i;
                y=&&intercept_g&i + &&cut_slp_g&i* &&x_&i;
                &group=&i;
                output;
                x=&cutscore;
                y=&&intercept_g&i + &&cut_slp_g&i* &cutscore;
                &group=&i;
                output;
            %end;
        end;
    run;
    data regdis2;
        set regdis2;
        if &group=1 then group='treatment';
        else group='control';
    run;
    ** スタイルの定義;
    proc template;
    define style Styles.rdplot;
        parent = Styles.Listing;
        style GraphData1 from GraphData1 / 
            markersymbol = "circle"
            color = blue 
            ;
        style GraphData2 from GraphData2 / 
            markersymbol = "triangle"
            color = red 
            ;
        end;
    run;
    ** グラフ出力;
    ods html path='/folders/myfolders' file='rdplot.html' style=Styles.Rdplot;    
    ** グラフ描画;
    proc sgplot data=regdis2;
            refline &cutscore / axis=x;
            scatter x=&pretest y=&posttest /name='plot' group=group %if "%upcase(&plotdata)"="N" %then markerattrs=(size=0);;
            series x=x y=y /group=group;
            xaxis label="pretest"  minor;
            yaxis label="posttest" minor;
            keylegend 'plot' /noborder across=2 title='Intervention Group';
    run;
    quit;
    ods html close;

%mend regdis;

参考文献

Hahn, J., Todd, P., & Van der Klaauw, W. (2001). Identification and Estimation of Treatment Effects with a Regression-Discontinuity Design. Econometrica, 69(1), 201–209. doi:10.1111/1468-0262.00183
Hartmann, W., Nair, H. S., & Narayanan, S. (2011). Identifying Causal Marketing Mix Effects Using a Regression Discontinuity Design. Marketing Science. doi:10.1287/mksc.1110.0670
Imbens, G. W., & Kalyanaraman, K. (2012). Optimal Bandwidth Choice for the Regression Discontinuity Estimator. Review of Economic Studies, 79(3), 933–959. doi:10.1093/restud/rdr043
Imbens, G. W., & Lemieux, T. (2008). Regression discontinuity designs: A guide to practice. Journal of Econometrics, 142(2), 615–635. doi:10.1016/j.jeconom.2007.05.001
Lee, D. S. (2008). Randomized experiments from non-random selection in U.S. House elections. Journal of Econometrics, 142(2), 675–697. doi:10.1016/j.jeconom.2007.05.004
McCrary, J. (2008). Manipulation of the running variable in the regression discontinuity design: A density test. Journal of Econometrics, 142(2), 698–714. doi:10.1016/j.jeconom.2007.05.005
Schoeneberger, J. (2011). RDPLOT: A SAS® MACRO for Generating Regression Discontinuity Plots. In SESUG Proceedings 2011. URL: http://analytics.ncsu.edu/?page_id=3375
Thistlethwaite, D. L., & Campbell, D. T. (1960). Regression-discontinuity analysis: An alternative to the ex post facto experiment. Journal of Educational Psychology. doi:10.1037/h0044319
2015/7/3 片桐

2015年10月14日水曜日

無料で SAS を使ってみよう 3: ETS が使えるようになった SAS OnDemand

概要

これまで、仮想環境、Amazon Web Service (以下、AWS) などで 無料版である SAS® University Edition を提供してきた SAS Institute 社ですが、第1弾の SAS Universiry Edition のライセンスが切れるこの時期になって、SAS OnDemand for Academicsを繰り出してきました。これまでとの大きな違いは以下の2点に集約されます。
  • 導入が非常に簡単。 仮想化ソフトのインストールや AWS の登録も不要です。SAS社の公式サイトでユーザー登録すれば、あとはブラウザ上で動きます。
  • SAS/ETS®, Enterprise Miner™ (EM), Enterprise Guide® (EG), Forecasting Server も使えるようになりました。 これまでの無料版では基本的なパッケージしか使えませんでしたが、今回はより高度な分析手法を提供してくれる Econometrics and Time Series Software (ETS) や EM 等も利用可能です。SAS EG も SAS のコーディングを意識しなくても GUI の操作だけでデータの加工ができる手軽さから、導入している企業も多いかと思います。特に今回は、SAS OnDemand の導入方法だけでなく、SAS/ETS の使い方の例を1つ紹介しておきます。

導入方法

それでは導入方法を紹介します。と言っても今まで (http://blog.n-insight.co.jp/2014/09/sas.html) よりもさらに簡単なのでほとんど書くことはありません。規約についても、私が見た限りでは University Edition の頃とあまり変わってないようです。
では実際に導入してみましょう。日本語版ページは ここにありますが、8月31日現在詳しいマニュアルは英語のみです。http://support.sas.com/ondemand/steps.html
唯一やるべきことは、ブラウザを開き、公式サイトでユーザ登録をすることです。
ブラウザは IE・FireFox・Google Chrome・Safari など主要なものはすべて使えます。 すでに SAS University Edition の登録を済ませていた場合でも登録が必要ですが、登録済み場合は新しいライセンスに同意するかどうかを入力するだけで登録が完了します (ID・パスワードは以前のものをそのまま使用できます)。
このような画面が出ます。まずは下方の 「Register for an account」をクリックしてユーザ登録をします。これ以降、すべて英語ですが、難しいことはなく、名前等を流れで記入するだけです。
登録が完了し、先ほどのサインイン画面に戻ってログインすると以下のような画面になります。
ここで、青字の 「SAS® Studio」をクリックすれば早くも SAS を起動できます。なお、下の「Courses I teach (create a new course)」 という項目は、今回から提供された、大学教員向けのSASを使った教育プログラム作成機能で,SAS Enterprise Miner 等を利用したい場合もここから新しい授業コースを作成するという形で利用できますが、これの説明は別の機会にしたいと思います。
あとはいつもの SAS Studio の画面です。

SAS/ETS® について

以下は、SAS/ETS の紹介です。やや専門的な話題なので、単に SAS OnDemand の導入をしたいだけの場合、読み飛ばしても問題ありません。また、計量経済学の知識があるか、すでに『その回帰分析、本当に因果関係ありますか? - 操作変数法の話 -』を読んでいた方向けです。
SAS ETS とは、計量経済学 (econometrics) や時系列 (time series) 分析を行うためのプロシジャを提供してくれるパッケージです。たとえば、以前 『その回帰分析、本当に因果関係ありますか? - 操作変数法の話 -』というタイトルで記事を書きましたが、2段階最小二乗法を実装するため、REG プロシジャを2回繰り返して実行しました。一方 ETS では、SYSLIN プロシジャを使えば 1回のプロシジャで実行できます (SYSLIN プロシジャの公式リファレンスはこちらです)。
ただし、SAS OnDemand ではデータセットを先にアップロードする必要があります。左側のファイラで、「ファイル (ホーム)」 を右クリックして「ファイルのアップロード」を選び、ファイルをアップロードしてください。今回はデータセットに https://ideas.repec.org/p/boc/bocins/griliches76.html からダウンロードした .dta ファイルをインポートしています。これをインポートし、前回と同様の分析をするプログラムが以下です。
/* .dta形式のデータセットを読み込む*/
proc import datafile='/home/ここにユーザー名/griliches76.dta'
    out=work.grilic
    dbms=dta replace;
run;
data work.grilic;
    set work.grilic;
    y_67 = (year=67);
    y_68 = (year=68);
    y_69 = (year=69);
    y_70 = (year=70);
    y_71 = (year=71);
    y_72 = (year=72);
    y_73 = (year=73);
run;
proc syslin data=work.grilic 2sls;
    endogenous  S IQ;
    instruments EXPR TENURE RNS SMSA y_: MED KWW AGE;
    wage_function: model LW = S IQ EXPR TENURE RNS SMSA y_: /overid ;
run;
SYSLIN プロシジャは REG プロシジャとは構文が異なります。ENDOGENOUS 文は、「内生」変数を記入するところです。内生変数、つまり外部からの影響を受ける可能性のある変数は、教育を受けた年数 (S) と 知能指数 (IQ) でしたので、この2つを入力します (厳密には、左辺の被説明変数 (LW) も内生変数と呼ばれるので、「被説明変数いがいの内生変数」を列挙します)。
次に、 INSTRUMENTS 文は、操作変数のリストです。残りの説明変数と、新たに加える操作変数のリストです。これは以前のやり方における、1段階目の REG のモデルの説明変数と同じです。
最後に、 MODEL 文にモデルを記入します。以前のやり方での2段階目の REG のモデルに相当します。以前は Shat, IQhat という変数名を使用していましたが、今回は1段階目の計算を自動で実行してくれるので、単に model LW = S IQ ... ; と書きます。 また、スラッシュのあとのオプション overid は、過剰識別の検定を行います。前回は Sargan 検定でしたが、overid オプションでは Basmann による方法で、若干計算方法が異なります。

これで2段階最小二乗法を計算した結果、係数は前回とほぼ同じ数値が出ました。さらに、Basmann 検定も、帰無仮説を棄却できていません。Basmann 検定も Sargan 検定も、帰無仮説の棄却は操作変数が正しく選ばれていないことを意味します。

2015/09/02 片桐

2015年10月2日金曜日

SASとMySQLにおける「null値」の扱い方の違いによる問題


以前に携わった案件でRDBMSとしてMySQLを使い、帳票作成やデータの更新処理はSASを通して行うシステムの開発がありました。

その際に、SASとMySQLにおける「null値」の扱い方の違いで苦しめられたことがあったので、自分の備忘録も兼ねて書いておこうと思います。

まず、SASには【In-Datebase】というサービスがあります。
これがどういったものかざっくり説明すると
『DB側で処理できる処理はDB側で処理してもらっちゃおう!』
というものです。名前のまんまですね。

パススルーを用いてSQL文を直接DB側に投げて処理させることもできるのですが、この【In-Database】のすごいところは
『SASのコードで書いた処理でも、DB側で処理した方が良い処理は、自動変換してDB側で処理させちゃう!』
ところです。賢いですね!

ただ今回の件は、この賢さが故に起きてしまった問題なのですが・・・


それでは前置きはこのくらいにして、今回起きた問題について書いていこうと思います。

例えば、以下に示すようなデータがMySQL上に存在したとします。

テーブル名「sample」
スキーマに割り当てたライブラリ参照名「db」
※四郎さんの郵便番号は「ブランク」、五郎さんの郵便番号は「null値」








上記データを「郵便番号」・「年齢」の昇順でソートしたデータをSASのワーク領域に抽出したい場合

  proc sort data = db.sample
                out  = work.sample ;
    by post_no age ;
  run ;

となります。

なんの変哲もないただのソート文なのですが・・・
SASは「null値」と「ブランク」は同じ文字値の欠損値として扱うのに対し
DB上では「null値」と「ブランク」は別のものとして扱うため
上記のソート文を実行した時に作成される「work.sample」は
【In-Database】で処理を行った場合とそうでない場合で以下のような違いが生まれます。

【In-Database】で処理していない場合








【In-Database】で処理した場合








抽出後のデータはSASデータセットなので、「null値」は「ブランク」に変換されます。
そして、注目していただきたいのは四郎さんと五郎さんの並びです!

【In-Database】を用いない場合は、DBからデータをSAS側に抽出してからソートを行うため、ソートの段階で「null値」と「ブランク」の区別はありません。

そのため、四郎さんと五郎さんの「郵便番号」は同一となり、第2ソートキーの「年齢」によって昇順にソートされます。

これに対して、【In-Database】を用いた場合は、先ほどのソートはDB側で行われて、ソートした状態のデータをSAS側に送ります。

DB側では「null値」と「ブランク」は区別され、「null値」は「ブランク」よりも更に小さい値として処理されてしまうため、五郎さんの方が、昇順で上にきてしまいます。


さて、ソート順くらい。。。と思う方もいらっしゃるかと思うのですが、、、
ここで問題発生です!!!

上記の【In-Database】を用いてソートを行ったはずのデータセットですが、並び順が本来SASでソートした順番とは違うため、DATAステップ等でグループ処理を行おうとすると、もちろんエラーになります。

つまり、以下のプログラムを【In-Database】のサービスを利用している状況下で実行するとエラーになります。

  proc sort data = db.sample
                out  = work.sample ;
    by post_no age ;
  run ;

  data work.test ;
    set work.sample ;
    by post_no age ;
    if first.age = 1 then output ;
  run ;

ログには『「work.sample」はちゃんとソートされていません。』的なログが出ます。
目の前でソートしてるのに・・・


対処法としては、「null値」と「ブランク」が混在する可能性があるデータの場合、ソート処理の前にSASデータセットとして抽出してから処理を行うことです。

もっとそもそもな方法としては
『テーブルを作成する段階で制約を設けて「null値」で登録できないようにすること』
もしくは
『「null値」と「ブランク」が混在しないようなシステムにすること』
になります。

DBのテーブル定義は思ったより奥が深く、本当に色んなことができます。
DBをただのデータの入れ物にしないように、これからも勉強を続けていきたいです。

ちなみに今回の「null値、ブランク」問題は単純なデータ抽出(where句等で)を行う際にも立ちはだかるようです。
便利なサービスも使いこなしてこそですね。

2015年9月18日金曜日

無料で SAS を使ってみよう2〜アマゾンウェブサービス編〜

以前、こちらで導入方法を紹介しました SAS® University Edition ですが、クラウドサービスであるアマゾンウェブサービス (AWS) からも利用できるようになりました (公式サイト)。 そこで、AWS版の導入方法について紹介したいと思います。

従来版とAWS版の違い

SAS® を試してみたいけどどっちを使えばいいかわからないという方、もしくは従来版をすでに使っていて、AWS版はどう違うんだ、という人のために先に特徴を簡単にまとめておきます。
  • 従来版
    • ローカルで作業できる
    • 無料
    • 仮想マシンのインストールや設定作業が面倒
  • AWS版
    • インストールが必要ない
    • やや速い?
    • SAS自体は無料だが1年後からAWSの利用料金が発生する場合がある
    • アマゾンウェブサービスのアカウント作成と設定が必要
SAS® University Edition 自体は従来版、AWS版いずれも無償ですが、アマゾンウェブサービス自体のシステムとして、アカウント登録から1年以内ならば条件つきで無料、それ以降は月額料金がかかる、というシステムなので注意が必要です1
AWS 版 SAS® University Edition の利用規約も英語ですが、直接利益を得るような使用はだめで、あくまで学習・学術用途に限ることとか、プログラムの逆解析や無断再配布といった著作権侵害行為をしてはならない、とか 18歳未満の方は保護者の同意のもとで使用すること、といった従来版とだいたい同じで常識的な内容です2が、Webサービスなので、次のような追加の条件があります.
  1. SAS Institute社の製品開発・品質向上のためソフトの使用に関する匿名の情報送信に協力すること。
  2. 個人で利用すること. 複数人で利用してはならない. また、第3者による不正なアクセスをされないようにする。
  3. プログラムやドキュメントをローカルにコピーしてはならない。
(1) は最近のWebサービスではよくある条項ですが、個人情報を送信されるのが気になるという方もいるかもしれませんのでご注意ください。 (2) は、クラウドサービスですがあくまで個人の学習用なので、グループでの利用はできないようです。

導入方法

アマゾンウェブサービスのアカウント作成ができたら、SAS社公式サポートページ "How do I run SAS University Edition on Amazon Web Services Marketplace?" を参考に SASを起動します。現時点では SAS社のサポートページも、マーケットプレイスも英語のページしかないので、日本語で簡単に説明しておきます。
まず、アマゾンウェブサービスのマーケットプレイス (いつもの通販サイトとして利用しているサイトではありません!) にて、sas university edition を探します。このページの一番下に利用規約 (End User License Agreement) があります。同意できるのなら、ページ右上の Continue をクリックします (ここまで英語ページの1.、2. に相当します)。 Continue ボタンの下にリージョン選択がありますが、これは何でもいいようです。
3. 次に SAS® University Edition の設定を行います。 (1) 1-Click Launch タブを選択していることを確認し、(2) EC2 Instance Type は t2.micro を選択します (他のを選ぶこともできますが、その場合アマゾンウェブサービス1年間無料枠の適用外なので料金が発生します。)。
(3) 一番下のKey Pair は設定せずに、左上の “Accept Terms & Run 1-Click” をクリックします。
4. いよいよ起動です。 画面右上の ``‘Your Account’’ をクリックし、移動先ページの “manage your woftware subscription” をクリックします。
すると、一覧に SAS University Edition のインスタンスが作成されています。ここで画像の黒塗りの部分にインスタンスIDが表示されます。 これはログインパスワードになるので、規約に従って隠しています。これはコピーしておきましょう。 右側の “Access Software” をクリックします。ダイアログボックスが現れ、ユーザIDとパスワードを訊かれるので、ユーザIDに “sasdemo” パスワードにさきほどコピーしたインスタンスID を入力します。
ログインに成功すると、従来版と同じようなスタート画面が表示されます。「お知らせ」欄にアップデートの通知が来てるときは適宜更新しましょう。初回はたぶん更新通知が来ていると思います。
「SAS Studio を始める」をクリックすれば SAS を利用できます。
ダウンロードとインストール作業がないぶん, 従来版より時間はかかりませんが, アマゾンウェブサービスの無料利用は1年だけなので留意ください。

AWS版利用の際の Tips

インスタンス終了・再開の方法

1年間無料の場合, t2.micro インスタンスは月750時間まで無料なので, 実行する必要は少なそうですが, インスタンスの停止・再起動についても補足説明しておきます。 SAS Studio をログアウトした後、マーケットプレイスの “manage your woftware subscription” から “manage in AWS Console” をクリックし、アマゾンウェブサービスのEC2管理コンソールへ移動します。 左のタブから「インスタンス」をクリックし、SAS® University Edition のインスタンスを選択し、右クリックメニューもしくは「アクション」から、「インスタンスの状態」を選び、「停止」・「再起動」を選択します。「削除」を選んだ場合、インスタンスが削除されるので、永久ライブラリに保存したデータセットなども削除されます。なお、インスタンスはリージョンごとに表示されるので、起動したはずなのに一覧にない、という場合はリージョンが違う可能性があります。リージョンは右上で変更できます。

フォルダの扱い

AWS版 SAS University Edition はアマゾンウェブサービスのサーバ上で動かしているため、自分のパソコンにあるファイルを直接開くことはできません。画面左のアイコンをクリックすればアップロードが可能です。
ファイルやライブラリのパスを指定するときは、従来版と同じように /folders/myfolders/ その配下にアップデートしたファイルや、作成したフォルダを指定します。
以下は、“Hello,SAS!” とだけ書いた test.txt というファイルをアップデートし、それを読み込んでログに表示させるプログラムの実行結果です。

新機能・ビジュアルプログラミングについて

AWS版でも従来版でも最新のものにアップデートすればできるのですが、「ビジュアルプログラマ」という新機能が追加されました。プログラムを処理ごとに分割してフローチャート図のように表すことで、流れをわかりやすくしたり編集をしやすくしたりできます。画面右上の「SASプログラマ」をクリックして「ビジュアルプログラマ」を選ぶと以下のような画面になります。
フロー画面

クエリ作成画面

ビジュアルプログラミングは左上の + マークを押せば新しくユニットを作成できます。プログラム・クエリ・サブフローが選べます。クエリは SQL クエリのようにデータセットの結合・ソート・フィルタなどができます。この機能は SAS® Enterprise Guide (公式サイト 、略称 EG) という製品に似ています。 SAS® EG はクエリ以外にも、さまざまなグラフを作成したり回帰分析や多変量解析、時系列分析などの分析を実施したり、それらをレポーティングしたりといったことを、プログラムをあまり意識せずに実行することができます。

  1. アマゾンウェブサービス上でSAS の利用に必要なサービスは Amazon EC2 という仮想サーバを提供するサービスです。これは t2.micro インスタンス (仮想サーバ) の使用を月750時間以内におさえている限り無料です 。ただしこれは現時点のものですので、登録前に必ずアマゾンウェブサービスのサイト『AWS クラウド 無料利用枠』や『AWS 無料利用枠提供規約』などで利用枠の詳細をご自身でご確認ください。
  2. 2015年5月22日現在、英語のみですが、将来的に公式日本語版規約が公表されるかも知れません. またここでの概要はあくまで記事執筆者である私の個人的解釈ですので、規約の同意は自己責任でお願いします.

2015年9月3日木曜日

平均から分位点へ:分位点回帰

過去のブログエントリにおいて、
「高学歴ほど収入の振れ幅が大きい」とのお話がありました。
以下の論文は、回帰分析でその問いに答える研究をしています。
  
Angrist,Chernozhukov, and Fernandez-Val (2006) “Quantile Regression Under Misspecification, with an Application to the U.S. Wage Structure”

ではこの論文ではどのように分析したのでしょうか。
今回は分位点回帰(Quantile Regression)のご紹介です。


振れ幅が大きくなる現象をどう捉えるか 

収入の振れ幅が大きいとは格差が大きいということなので、
データがより広く散らばっていることになります。
言い換えると、分散が大きくなっていることになります。

つまり学歴が高くなるにつれて、
分散が大きくなることを確認すればよいことになります。
単回帰分析であれば以下のように散布図を作成すれば、容易に確認できます。


しかし、現実ではそうは簡単にいきません。
例えば重回帰分析の場合、散布図では確認することはできません。
では、どのようにすれば分析できるでしょうか。


分位点で回帰する分位点回帰(Quantile Regression) 

上の散布図において、
x(横軸)ごとのy(縦軸)の最小値付近を対象にすると、傾きはゼロになります。
対してxごとのyの最大値付近をみると、恐らく傾きは1程度になるでしょう。

例えば、yの分布の両端を対象にそれぞれ回帰直線を引くと、
以下のような 線になります。


つまり格差が拡大するケースでは、
分位点が最大値に近づくにつれて、傾きが大きくなるはずです。
このように平均ではなく、分位点を用いた回帰分析を、
分位点回帰(Quantile Regression)といいます。

種明かしをしますと、上の図における直線は
90%と10%のそれぞれの分位点で
分位点回帰を実行した回帰直線です。

この2つの回帰直線の傾きの差が大きいほど、
格差が拡大していくということになります。

ちなみに通常の回帰直線はこんな感じです。
違いがお分かり頂けたでしょうか。

 


ここまでのまとめ 

・ 分位点回帰は平均以外の分布の切り口を使って回帰分析ができる

・ 説明変数(横軸の変数)の値によって被説明変数(縦軸の変数)の格差が拡大
 することを見たい場合:
        ↓
 分布の両端(例えば10%と90%の分位点)で分位点回帰を行い、傾きの差を見る。


話を戻すと… 

話を戻しますと、今回のエントリの目的は、
「高学歴ほど収入の振れ幅が大きい」ことを検証することにあります。

つまり収入と学歴の関係が、
上の散布図のようになっていればよいことになります。
しかし、現実では他の要素も関係してくるので、
分位点回帰で分析してみましょう。



使用データ  


まずはデータから。今回使用するデータは、
Angrist, Chernozhukov, and Fernandez-Val (2006)で使用されているデータです。
このデータは2000年、1990年、1980年にアメリカで行われたセンサスデータの一部です。

データは以下のURLからダウンロードできます。


早速データをインポートしましょう。


proc import datafile='C:\usr\usrname\folder\angcherfer06\Data\census00.dta'
    out =work.census
    dbms=dta replace;
run;


Angrist, Chernozhukov, and Fernandez-Val (2006)では、
分析に用いた変数は賃金と教育年数のみでしたが、他の変数も使用してみましょう。
今回は以下の変数を使用します。



今回は2000年のデータを用いて、分位点回帰を実行しましょう。
SAS/STATのquantregプロシジャで実行できます。
分位点はmodelステートメントのq=オプションで指定します。

今回は10%、25%、50%、75%、90%の分位点で実行します。

ちなみに50%分位点は、
メディアンを使った「最小絶対偏差推定(Least Absolute Deviation Estimation:LAD推定)」です。


proc quantreg data = census ;
   model logwk = educ exper  black / quantile =.1 .25 .5 .75 .9;
   weight perwt ;
run ;


結果出力中の「Quantile and Onjective Function」の表にあるQuantileの項目が分位点を表しています。
上から10%、25%、50%、75%、90%の順番で表示しています。


res1.PNG
res2.PNG


res3.PNG


教育年数(educ)に注目してみると、分位点が最大値に近づくにつれ、
傾きが大きくなっていることが分かります。
従って、学歴が高くなるにつれ、
収入の格差が拡大するという仮説を支持する結果であると言えます。
それでは80年のデータを使うと、どのような結果になるでしょうか。


proc import datafile='C:\usr\usrname\folder\angcherfer06\Data\census80.dta'
  out =work.census
  dbms=dta replace;
run;

proc quantreg data = census80 ;
  model logwk = educ exper  black / quantile =.1 .25 .5 .75 .9;
  weight perwt ;
run ;




この結果をみると、10%と90%の分位点における傾きの差は、
2000年に比べて小さいことが分かります。
つまり20年の間に労働市場の構造が変化したことになります。

また、2時点間において黒人ダミー(black)の係数値にあまり変化が見られません。
人種による収入の格差が如何に根深いかが伺えます。



分位点回帰のメリット 

最後に分移転回帰のメリットを2点挙げます。
1.外れ値に依存しない
  • 最小二乗法は平均値を用いるため、外れ値に大きな影響を受けます。
    一方で分位点回帰は、メディアンなどの分位点を用いるため、外れ値に影響されにくくなります。

2.分布の形の変化を掴むことができる
  • 分位点ごとの回帰を行うことで、説明変数の値の変化と共に、
    被説明変数の分布の形がどう変化するかを分析することができます。
    今回の投稿ではこちらのメリットを活用しました。

今回は理論的な部分には触れませんでしたが、
基本的な理論とその応用については以下の本がおすすめです(訳本もあります)。


Mostly Harmless Econometrics: An Empiricist's Companion
(邦題:「ほとんど無害」な計量経済学―応用経済学のための実証分析ガイド)
著者:Joshua Angrist and Jörn-Steffen Pischke






2015年8月13日木曜日

SQLのトランザクション処理におけるデッドロックについて

今回は、以前に開発していたシステムで実際に起きたSQLにおけるデッドロックについて、備忘録として書いていこうと思います。


まずはデッドロックについて少し前置きを・・・

例えば、DBに対してトランザクション処理(一連の処理をまとめたもの)を行った際に、違うトランザクション処理と競合してしまい、処理結果が求めていたものと違う形になってしまったら、もちろん困りますよね?

もちろんこういった困ったことが起きないように、現在広く使われているRDBMSでは、処理を行う対象のテーブルにロックをかけてから処理を行うことでこのような問題を防いでいます。

ただし!!

今回の問題は、このロックをかけることによって起きてしまいます。。

再び例え話なのですが、私がDB上のあるテーブルに対してロックをかけようとした時に、既に違う誰かがロックをかけていたら、もちろんその人がロックを解くのを待つしかありませんね?

ただ、もしその既にロックをかけていた人も私がロックを解くのを待っていたとしたら?

お互いがお互いのロックが解かれるのを待っているのですから、一生待ち続けることになります。

そして、ロックをかけないと処理を行うことはできないため、この時点でトランザクション処理自体が先に進むことができなくなり、死んでしまいます。

つまり『デッドロック』です!

さて、そもそもお互いがお互いのロックを待つなんて不思議な状況は本当にあり得るのでしょうか?

まぁあり得なかったらこの記事はなんのための記事か分からないのですが・・・

全てのことの発端は、ロックには「排他ロック」と「共有ロック」という2種類のロックが存在することから始まります。

それぞれのロックについて簡単に説明すると・・・

【排他ロック】
専有ロックとも言われ、その名の通り対象のテーブルを専有してしまうロックです。
このロックがかかっている間は他の人はそのテーブルには手出しできません。

【共有ロック】
こちらも名前のまんまなのですが、他の人と共有できるロックになります。
私が共有ロックをかけている場合でも、違う人は同じテーブルに共有ロックをかけることができます。
ただし、排他ロックをかけることはできません。


はい。ざっくりではありますが、ここまででデッドロックとロックの種類に関する前置きは終了です。

それでは、今回起きた現象について、書いていこうと思います。

今回のシステムで実行していたトランザクション処理を言葉にすると
「テーブルにデータを登録した後に、不要になったデータを削除する」
という処理です。

例えば、テーブルに50件データを保持しておきたくて、データを新しく追加する度に古いデータから削除していく場合です。

今回はテスト用に適当なテーブルを用意して処理を行います。

  create table sample(
    id INT(11) NOT NULL AUTO_INCREMENT ,
    detail VARCHAR(10) ,
    PRIMARY KEY (id) ) ;

※「id」にはAUTO_INCREMENTを指定しているので、値を指定しない場合は前に挿入したレコードにの値に+1した値を設定していきます。

それでは以下トランザクションのSQL文です。

【トランザクション1】
  begin ;

    /* インサート */
    insert into sample(detail) value ("test1") ;

    /* 削除対象「id」の値を変数に格納 */
    set @del_id1 = (select max(id) - 50 from sample) ;

    /* デリート */
    delete from sample where id < @del_id1 ;

  commit ;

【トランザクション2】
  begin ;

    /* インサート */
    insert into sample(detail) value ("test2") ;

    /* 削除対象「id」を変数に格納 */
    set @del_id2 = (select max(id) - 50 from sample) ;

    /* デリート */
    delete from sample where id < @del_id2 ;

  commit ;

※テーブルに50件以上データが入っていない場合は、削除処理は実行されますが、処理結果は0件です。

この2つのトランザクション処理について、【トランザクション1】のインサート文が実行されてから、デリート文が実行されるまでの間に、【トランザクション2】のインサート文が実行された場合、この2つのトランザクションの間でデッドロックが発生します。

さて、なぜデッドロックは発生したのでしょうか?

ここで大事になってくるのが、インサート文を実行することでテーブルにかけるロックは共有ロック、デリート文を実行することでテーブルにかけるロックは排他ロックだということです。

【トランザクション1】でインサート文を実行した時点で、【トランザクション1】はテーブルに共有ロックをかけます。

しかし、先程書いた通り、共有ロックがかかっている間でも、他の人も共有ロックを取得することができてしまうため、【トランザクション2】はインサート文を実行し、共有ロックを取得できます。

この状態で【トランザクション1】も【トランザクション2】もテーブルに対して共有ロックをかけている状態になります。

そして、それぞれのロックはコミットまたはロールバックされるまで解かれることはありません。

もうお分かりですよね?

つまり、【トランザクション1】はデリート文を実行するために排他ロックをかけようとした時に【トランザクション2】の共有ロックがはずれるのを待つことになり、【トランザクション2】もデリート文を実行するために排他ロックをかけようとした時に【トランザクション1】の共有ロックがはずれるのを待つことになるため、デッドロックが完成します。

言葉にすると上記の通りなのですが、図で説明すると以下の通りです。



















ただ、少し考えれば分かることなのですが、対処法は簡単です。

『共有ロックをかける前に排他ロックをかけてあげる』だけです。

排他ロックを最初にかけてしまえば、もう一方のトランザクションはロックが解けてから排他ロックをかけて処理を行うため、デッドロックは発生しません。

つまり、デリート文を先に実行してあげる、もしくは排他ロックをトランザクションの一番最初に取得するだけで解決できます。

ちなみに以下のSQL文で簡単に排他ロックを取得できます。

  select *
  from [テーブル名]
  for update ;

そのため、トランザクションの一番最初で対象のテーブルに対して、上記SQL文で排他ロックを取得してあげれば、デッドロックは発生しません。

ちなみに、排他ロックについては、where句で行単位に取得することができたり、ロックをかけようとして、既に違う人がロックをかけていた場合の待ち時間を指定したりもできるので、興味がある方は是非調べてみて下さい!

2015年7月13日月曜日

AMOを用いたデータ更新画面

本日は、AMOを用いたデータ更新画面の試作版を作成したので紹介致します!

ちなみにAMOとは『SAS® Add-in for Microsoft Office』の略で、要するにアドインのことです。
今回はExcelにこのアドインを入れて、Excelを用いた更新画面を作成しました。

インターフェイスはこんな感じです。











今回は、2画面作成しました。
右上のラジオボタンで画面の切り替えを行うことができます。

それでは、少しいじくってみましょう!
まずはデータの照会から!
照会ボタンを押下すると、ストアドプロセスの実行プロンプト画面が表示されます。

















今回の仕様では、3桁の「顧客ID」を入力します。
プロンプトの機能で半角3文字以外は入力できないようになっています。
「対象年」は省略可能で、省略した場合は現在の年のデータを取得します。
照会後の画面がこちら。











今回のデータソースは事前に作っておいたSASデータセットです。
データの内容が手抜き感丸出しなのは申し訳ないです・・・苦笑
データソースに関しては、CSVだろうと、RDBMSだろうと、SASが扱えるものならばなんでも大丈夫です。
ただし、更新処理においてトランザクション処理を行うことを考えると、やっぱりRDBMSがおすすめです!

ちなみに、照会する時にデータベースに存在しない顧客IDを照会しようとすると・・・










というように怒られてしまいます。。
このように、不整合な処理を実行しようとした場合、SAS側でチェックを行い、エラーメッセージをメッセージボックスに表示させます。

さて、今度は照会したデータを修正しようと思います。
現在の画面は参照モードなので、まず上の編集のチェックボックスにチェックを入れます。
すると、修正を行える項目だけセルの色が白に変わり、修正を行うことができるようになります。
実際に修正を行った後の画面がこちら。










更新画面2では、メニューをプルダウンメニューで選べるようになっています。
それぞれの入力値については、セルの書式設定で変な値を入れられないようにすることももちろんできます。
選択した行の色を変えることや、メニューごとの金額を取得すること、合計金額の算出については、全てエクセルの機能です!エクセルってやっぱり超便利ですね。

さて、値を修正したことですし、更新を行おうと思います。
更新ボタンの押下です。








すると、パスワードの入力画面が出てくるので、秘密のパスワードを入力します。
見事パスワードが正解だった場合、処理が実行されます。
実行されると・・・








というメッセージボックスが出てきます。
無事処理が行われたようですね。
そして、「自動照会済」と書いてあるように、実行後は自動で画面に更新後の最新情報を表示します。
更新後の画面がこちら。











更新画面2を見ていただくと分かるのですが、値が両方入っていないデータについては、登録されていません。
SASでデータの加工やチェックを行うことができるので、エクセル上でチェックできないようなデータの整合性のチェックはSAS側で行います。

では、最後に削除をしてみましょう。
削除ボタンを押下すると、同じくパスワードを入力する画面が出てきます。
もちろん更新と削除で別々のパスワードを設定することもできます。

削除を実際に実行してみると・・・










というメッセージボックスが表示され、マスタからデータが削除されます。
そしてデータを削除したので、画面からもデータを削除し、もとの状態に戻ります。









この他にも、前年、翌年ボタンで対象の顧客の年違いデータを1クリックで取得したり、印刷ボタンで画面を印刷することもできます。

更に、もっとグレードアップさせたいのであれば、マクロをショートカットキーに紐付けて、ショートカットキーで処理を行えるようにしたり、項目に値を入力したタイミングでマクロを起動して、データベースから対応する値を取得したりすることもできます。

発想次第で可能性無限大ですね!
ものづくりの楽しさを感じれる開発でした!

はい!それでは試作版更新機能の紹介は以上になります。

ツイート数からみる"バーチャルYouTuber"ブーム

今や YouTuber の話題の半分を占めるほどのクチコミ数に 当社が提供するソーシャルビッグデータ検索ツールの「 beInsight (ビーインサイト)」を使って、話題の「バーチャル YouTuber 」について調べてみました。 「バーチャル YouTuber...