作者:吳雄 (湘潭大學) Stata 連享會: 知乎 | 簡書 | 碼雲
作者:吳雄 (湘潭大學)
之前,我在處理數據的時候,經常碰到一些非平衡面板數據,當時處理完後才發現連玉君老師之前已經編寫了一個 xtbalance 的命令,該命令專門用於將連續時間非平衡面板處理成平衡面板。但是,該命令在處理非連續時間的非平衡面板有點缺陷,所以平時我還是自己寫命令來處理非平衡面板數據的問題,這兩天我發現有同學還有一些別的交流群里的群友在用的時候就碰到這個問題,今天,我就打算細講如何將非平衡面板轉換成平衡面板。
xtbalance
首先,這個命令是 Stata 外部命令,需要先下載安裝才能使用。下載安裝的命令為: ssc install xtbalance。完成後,輸入 help xtbalance 查看幫助文檔,以了解該命令的使用方法。
ssc install xtbalance
help xtbalance
xtbalance 的語法格式: xtbalance, range(numlist) [ miss(varlist) ]
xtbalance, range(numlist) [ miss(varlist) ]
xtset panelvar timevar
tsset panelvar timevar
接下來,你可以根據所需時間段來處理數據,比如我需要 1992-1998 年的平行面板,命令為 xtbalance, range(1992 1998)。
xtbalance, range(1992 1998)
timevar
//數據生成 . set obs 100 . gen id = int(_n/5.001)+1 . bysort id:gen year = 1992 +2*(_n-1) . xtset id year
panel variable: id (strongly balanced) time variable: year, 1992 to 2000, but with gaps delta: 1 unit
//取1992-1998年段的平衡面板 . xtbalance, range(1992 1998)
(20 observations deleted due to out of range) (80 observations deleted due to discontinues)
我們這裡就不貼xtbalance命令的源代碼,但是我通過自己編寫的一個do文件來展示我猜測的具體操作流程。
我們首先生成一個 id 為 0 (1) 99,year 為 1991 (1) 2000 的平衡面板:
id
year
. clear . set obs 1000 . gen id =int(_n/10.000001) . bysort id :gen year = 1990 + _n . xtset id year
panel variable: id (strongly balanced) time variable: year, 1991 to 2000 delta: 1 unit
然後,我們生成均勻分布的隨機數,將隨機數小於 0.2 的樣本刪掉,即每條都有 20% 的概率被刪掉,剩下的樣本為非平衡的樣本
. drop if runiform() <0.2 . xtset id year
panel variable: id (unbalanced) time variable: year, 1991 to 2000, but with gaps delta: 1 unit
同時,通過tab id我們可以看每個id的樣本數(受限於編輯器,這裡只列出幾行)都不一樣
tab id
. tab id
id | Freq. Percent Cum. ------------+----------------------------------- 0 | 6 0.73 0.73 1 | 9 1.10 1.83 2 | 8 0.98 2.81 3 | 9 1.10 3.91 4 | 7 0.86 4.77 5 | 9 1.10 5.87
實際上,xtbalance 命令的實現是這樣的:
刪除不在時間段內的樣本; 計算每個id的樣本數,如果每個 id 組內缺少樣本,則將這個 id 的樣本都刪除。
假如,我們需要將上述數據 id : 0 (1) 99 year: 1991 (1) 2000的非平衡面板轉為 id :0 (1) 99 year: 1992 (1) 1998的平衡面板的話,我們需要知道當轉為平衡面板後,每個id相對應的只有1998-1992+1=7條記錄
. preserve . drop if year > 1998 | year < 1992 (243 observations deleted)
. bysort id :keep if _N ==7 (400 observations deleted)
. xtset id year panel variable: id (strongly balanced) time variable: year, 1992 to 1998 delta: 1 unit . restore
. xtbalance, range(1992 1998)
(243 observations deleted due to out of range) (400 observations deleted due to discontinues)
. xtset id year panel variable: id (strongly balanced) time variable: year, 1992 to 1998 delta: 1 unit
實際過程中,有許多資料庫並不是連續時間的面板,這可能是因為多種原因,比如,某個資料庫在調查數據時候,分別在 1990、1992、1994 每兩年調查一次的,其實,這種滿好的,因為有固定間隔,然而,當不是固定間隔的時候,處理數據的時候你可能需要多留意。
先生成平衡面板(不是連續時間)
*-生成非連續時間的平衡面板 . clear . set obs 1000 . gen id =int(_n/10.000001) . bysort id :gen year = 1990 + 2*_n -1 . xtset id year panel variable: id (strongly balanced) time variable: year, 1991 to 2009, but with gaps delta: 1 unit
. xtset id year, delta(2) panel variable: id (strongly balanced) time variable: year, 1991 to 2009 delta: 2 units
. tab year
year | Freq. Percent Cum. ------------+----------------------------------- 1991 | 100 10.00 10.00 1993 | 100 10.00 20.00 1995 | 100 10.00 30.00 1997 | 100 10.00 40.00 1999 | 100 10.00 50.00 2001 | 100 10.00 60.00 2003 | 100 10.00 70.00 2005 | 100 10.00 80.00 2007 | 100 10.00 90.00 2009 | 100 10.00 100.00 ------------+----------------------------------- Total | 1,000 100.00
*-直接使用xtbalance的缺陷/ . preserve
. count 1,000
. xtbalance, range(1993 2005)
(300 observations deleted due to out of range) (700 observations deleted due to discontinues)
. count 0
. restore
xtset id year
tsset id year
time variable
xtset id year, delta()
delta()
再通過隨機刪除部分樣本,使其成為非平衡面板:
. drop if runiform() <0.2 (168 observations deleted)
. xtset id year,delta(2) panel variable: id (unbalanced) time variable: year, 1991 to 2009, but with gaps delta: 2 units
我們所需要的樣本時間段為 1993(2)2005:
year | Freq. Percent Cum. ------------+----------------------------------- 1991 | 78 9.38 9.38 1993 | 84 10.10 19.47 1995 | 80 9.62 29.09 1997 | 82 9.86 38.94 1999 | 82 9.86 48.80 2001 | 88 10.58 59.38 2003 | 79 9.50 68.87 2005 | 86 10.34 79.21 2007 | 87 10.46 89.66 2009 | 86 10.34 100.00 ------------+----------------------------------- Total | 832 100.00
我們所需要的是 1993(2)2005 的時間段的話,每個 id 在 1993(2)2005時間段內的樣本數應該是1+(2005-1993)/2 = 7,所以,我們的操作流程就是:
. preserve
. drop if year>2005 | year <1993 (251 observations deleted)
. bysort id :drop if _N != 7 (413 observations deleted)
. xtset id year,delta(2) panel variable: id (strongly balanced) time variable: year, 1993 to 2005 delta: 2 units
對於有固定間隔的平衡面板數據,我們可以預先生成一個新的時間變數 (連續的),進而使用 xtbalance 命令進行處理。
. xtset id year, delta(2) panel variable: id (unbalanced) time variable: year, 1991 to 2009, but with gaps delta: 2 units
. bysort id: gen new_year = _n //使用該命令前一點要先對數據排序 * 或 gen new_year = 1 + (year - r(min))/2
現在 1993 年在 new_year 中就是 2,而 2005 年就是 8 ,然後用新的時間來設置面板,再使用xtbalance,range(2 8) 就OK了
xtbalance,range(2 8)
. xtset id new_year panel variable: id (unbalanced) time variable: new_year, 1 to 10, but with gaps delta: 1 unit
. xtbalance,range(2 8)
(251 observations deleted due to out of range) (413 observations deleted due to discontinues)
股票日交易資料有一個典型的特徵:所有公司的資料在非交易日都是缺失的。因此,雖然股票日交易資料本質上是一份連續數據,但 Stata 在接到 xtset id date 的通知後,將其視為非平衡面板數據。(Note: 這裡暫不考慮那些在交易日里停牌的公司)
xtset id date
此時的處理方法與上一小節相似:可以先使用 bysort id: gen new_data=_n 命令或 egen new_date = group(date) 命令生成新的時間變數。
bysort id: gen new_data=_n
egen new_date = group(date)
對於更為一般的情形,處理方法也會相對複雜:先刪掉不在時間段內的樣本,然後通過某種方法將你的時間變數轉為一個新的具有連續時間的變數,之後通過每個 id 的樣本數與為平衡時的樣本數進行比較,一樣則保留,否則刪除。
在寫作這篇推文過程中,我與吳雄多次溝通,受到了不少啟發。
後續我們會將文中提及的 xtbalance 的局限一一解決掉,以便大家能夠更為便捷地進行非平行面板 → 平行面板的轉換。
計劃添加的功能如下(歡迎各位補充,反饋至:[email protected] ):
gen(newvarname)
force
關於我們
Stata
Stata連享會
聯繫我們
Stata連享會(公眾號: StataChina)
五篇
往期精彩推文