Development Micro-econometrics Study Group: Code Notes

日本語で経済学分析に有用なコードの備忘録を作成しています。We provide explanations of useful codes in Japanese for data cleaning, analysis, visualization like memorandum. Our software focuses on STATA, R, Python.

STATAでcollapseしても変数の名前をキープする。

異なるobservation間で足し算をしたり、duplicateに対処するためにcollapseが有用である。しかし、例えば

collapse (sum) population, by(prefecture)

を実行すると、その後の変数prefectureのラベルは(sum) prefectureなどとなってしまい、もともとprefectureについていたラベルは消えてしまう。特に変数の数が多いとき改めて全部ラベルを付けなおすのは面倒である。すべての変数で、前の変数名をkeepしたい場合にはまずは以下をcollapseする前に実行し、名前を記憶させる。

  foreach v of var * {
    local l`v' : variable label `v'
        if `"`l`v''"' == "" {
        local l`v' "`v'"
    }
  }

そして、collapseの動作を行った後に、

 foreach v of var * {
    label var `v' "`l`v''"
 }

を実行すれば、全ての変数が前と同じラベルになる。

参照: FAQ: Keeping the same variable with collapse | Stata

STATAでlocal変数の共通部分を抜き出す。

localは、複数の変数を指定するとき、また、何かの結果を一時保存するのに非常に有用である。その組み合わせ技として、local変数同士から新たなlocal変数を定義したいことがあった(例は一番下)。ここでは、二つのlocalの組から共通の変数を新しいlocalとして定義することを考える。

まずは二つのlocalを定義する。

local cov1 "X1 X2 X3"
local cov2 "X2 X3 X4"

(これらのlocalは`cov1'などとすれば呼び起せる。)そしてこの共通部分である X2 X3を新しいlocalとして定義する。

local common : list cov1 & cov2

displayでうまくいったか確認する。

dis `common'

localはすべて同時に回さないといけないことに注意が必要である。例えば↑をひとつづつ実行しても記憶されない。

参考: Manipulating locals via macro lists

STATAで変数や文字列の組でループを回す。

STTAで文字列や変数のループを回すときに使うコード。localを用いて変数の組を作り、それぞれのグループの何番目かを指定することでループを作る。 例えば、ANCOVAで複数の回帰分析をループで回したいとき、outcomeとbaselineでのoutcomeの組を指定したい。

 global controls X1 X2 X3
        local Outcomes "Income Asset Expenditure" //
    local Outcomes_baseline "Income_baseline Asset_baseline Expenditure_baseline" //
    local n : word count `Outcomes'
    forvalues i = 1/`n' {
        local Y : word `i' of `Outcomes'
        local Yb : word `i' of `Outcomes_baseline'
       
    reg `Y' $controls `Yb',  robust


         }

としてやると

 reg Income $controls Income_baseline,  robust
    reg Asset $controls Asset_baseline,  robust
    reg Expenditure $controls Expenditure_baseline,  robust

を実行したのと同様である。

参照リンク: How do I process parallel lists?

Stataのegen sum()とgen sum()

変数を作成・加工する際に使用するsum()関数は、egengen(またはreplace)かによって、出力が異なる。

例えば、 以下のようなデータを考える。

id var1
a 1
b 2
c 3

この時、egengenそれぞれでvar1変数をsum()すると、

egen var1_sum_egen = sum(var1)
gen var1_sum_gen = sum(var1)
id var1 var1_sum_egen var1_sum_gen
a 1 6 1
b 2 6 3
c 3 6 6

となる。つまり、egen ... sum()では全ての合計値を返す一方で、gen ... sum()では上の行から順にvar1を足し上げた値(累積の合計値?)を返す。

ちなみに、replace ... sum()gen ... sum()と挙動は同じ。

STATAで複数の変数をまとめて指定する。

STATAで複数の変数を同時に指定したいときがある。例えば、所得が分類ごとに分かれているときに、それらをすべて足し合わせて総所得を計算するとき(変数を足し合わせるコマンドはここではegen rowtotalを用いる)などだ。以下では二つの方法を紹介する。 変数リストが

income_agriculture income_labor income_fish income_business

のように入っているとする。

  1. - を用いて、データセットの順番になっている変数を同時に取り出す。
egen n_SuvCom=rowtotal(income_agriculture - income_business)

とすれば、income_agricultureからincome_businessまでの間の変数を順番にすべて指定できる。ここで注意が必要なのは、順番通りに間の変数をすべて指定するので、間に別の変数が混ざっていたり、データセットをいじったりすると、変わってしまう恐れがある。

  1. *を用いて、特定の名前の変数をすべて取り出す。
egen n_SuvCom=rowtotal(income_*)

のようにすると、income_から始まる全ての変数を取り出すことができ、総所得を計算することができる。自分で変数の名前を工夫してつければ便利である。

STATAでlocal変数から特定の変数を落とす

STATAlocalを用いて変数の組を管理すると何度も入力しなくてよいし、途中で少し違うモデルを回すのが非常に楽になる。 しかしいちいち細かく定義していては全部手で入力しているのとあまり変わらないので、一度定義したものを少し変形して使うことでより綺麗なコードが書ける。ここでは、一度定義したlocal変数の組からある変数を除く。

例:

local covariate "age sex educ"

と入力することで`covariate'と入力すれば、age sex educの変数の組を呼び出すことができる。ここからeducを除いて、age sexのみの変数の組を使いたいとする。その時、

local educ "educ"
local covariate : list covariate - educ

とすれば、`covariate'age sexの組となる。確認するには、

di "`covariate'"

とすればよい。参考:

stackoverflow.com

Stataでデータセット結合:あなたが探しているのは「merge m:m」?それとも「joinby」?

二つのデータセットを、ある変数をkeyとして横方向で結合したい場合、多いと思います。
このkeyがそれぞれのデータセットでunique(被りがない)なら、普段通り、merge 1:1を使えば問題ありません。 また、一方のデータセットはkeyとなる変数がuniqueになっていて、もう一方のデータセットではkey変数に被りがある場合(例えば、村レベルのデータセットに、家計レベルのデータセットを村IDで結合)、merge 1:m, merge m:1、もしくはkey変数に被りがあるデータセットの形を変えてmerge 1:1してしまう、どの方法でもうまくいくかと思います。

問題が発生するのが、二つのデータセット両方でkey変数がuniqueになっていない時。 例えば、村IDが振られている家計レベルのデータについて、同じ村の中で家計を総当たりで結合したいとします。 その時、データセットの形が各村について家計がlong型ではいっているものを、そのまま結合に使いたいとすると、選択肢となるコマンドは merge m:mjoinby です(データセットの形を変えて、merge 1:1 などに落とし込む方法もありますが)。 この二つのコマンド、挙動が全く異なります。 この(総当たりでマッチしたい)時、正解は joinby です。 merge m:m では求めている結果を返してくれません。

実際にどんな感じになるか見てみましょう。 例えば、ここでは次のような仮想データを考えます。

data1

id_village household
1 A
1 B
2 A
2 B

data2

id_village household_2
1 A
1 B
2 A
2 B

この二つのデータをid_villageで横方向で結合すると、

merge m:m id_village using data2

は次のデータを返します:

id_village household household_2
1 A A
1 B B
2 A A
2 B B

つまり、key変数の値がuniqueでない時、それぞれのkey変数の値について、上からマッチした順に上から結合していくというものになります(なので、元のデータでの行の順番によって結果が異なります)。 ここから分かるように、総当たりでは結合してくれません。

一方、joinby だと、

joinby id_village using data2

とすると、次のデータを返します:

id_village household household_2
1 A A
1 A B
1 B B
1 B A
2 A B
2 A A
2 B B
2 B A

同じkey変数の値内で、householdhousehould_2 が総当たりで結合されています。 ただし、merge が結合できた行・できなかった行を新たな変数 (_merge) で明示してくれる一方、joinby はデフォルトではそうした変数を新たに作りません。 また、data1, data2 どちらかにしかない id_village の観測値は、マッチされないため削除されてしまうことにも注意です( merge では「マッチされない」ということが明示されます)。

ここからも分かる通り、merge m:m は求めているものと異なる挙動をしている場合が多く、かつ結果が元のデータの行の順番に依存している、危険なコマンドなため、できるだけ使わない方が良いそうです。

参考:Statalist: Merge m:m vs joinby