STATA 上的資料探索

CW Wayne Yeh
10 min readAug 29, 2021

--

資料敘述統計

做任何形式的分析前,經常需要先探索與描述資料。在不充分了解資料的情形下分析幾乎無異於瞎子摸象,此外描述資料也有助於偵錯(比如說某個回歸變數有不合理的極大極小值,或是大量的 missing)。下面介紹幾個有幫助的指令:

  • describe ,會概略地描述資料大小、樣本數、變數列表與儲存形式¹。其實,我們也可以在右下角的 Properties Block 找到相關資訊喔。
  • sum,可以對「數值」變數進行常見的敘述統計,加上 option , detail 則會進一步輸出如百分位、偏峰度等統計量。
  • codebook ,可以查看變數的細節(依變數類型而有異),如:變數類型、儲存形式、Range、Unique Value、Missing 等。

上述的幾個指令可以只用在選定的變數上,例如:sum price mpg, detail 。如果去查閱 help file(help <command> ),會發現有許多指令後面都可以選擇性地加上 argument <varlist>,也就是上列的變數清單 price mpg

describe、sum 回傳結果
Fig. 2–3 describe、sum 回傳結果

describesum 的輸出結果如 Fig 2-3 所示,各位不妨觀察一下有哪些資訊。

除了 sum 所提供的敘述統計量之外,我們有時也關心變數值的次數分佈,尤其是對於類別變數。tab <var>, m,可以顯示變數 <var> 的次數、比例、累積比例,option , m 則會 一併統計遺失值(missing)的次數。這個 option 並非預設,但我個人是習慣加上,畢竟很多時候 missing 是值得留意的訊息。若我們想對兩個變數做(聯合)次數分佈時(比如說:gender、race),可以使用 tab <var1> <var2>, m 。如果想進一步去看聯合比例、條 件比例的話,可以加入 cellrowcol 這些 option。這些指令除了有助於了解資料外, 有時候也可以用來確認生成變數的流程是否正確。比如說:我們可以用 tab <new_var>, m 來確認新變數的次數分佈是否合理、是否有不想要的遺失值。最後補充幾個也很實用的指令:

  • br <varlist> ,在 data browser 中瀏覽 <varlist> 所挑選的變數。忽略 arguement <varlist> 時則是會瀏覽全部的變數,這相當於直接點選 Tool Bar 上的「data browser」。讀者在讀入新資料後,建議可以先 br 一下,對該資料有一些基本的概念。此外,生成新變數後也可以用 br 做個粗略的檢查。
  • tabstat <varlist1>, by(<varlist2>) s(<statistic>) ,以 varlist2 分組(通常是類別變數),回報每個組別 varlist1 的統計量 <statistic>。這個指令可以視為 tabsum 的活用,一些像是統計量名稱的細節,都可以在 help file 查詢。
  • corr <varlist> ,相關係數矩陣。option , c 則可以回報共變異數矩陣。

除了計算敘述統計量之外,繪製直方圖、散佈圖之類的圖表也是很好的方法(see 2–5)。最後強調一下,我無法在此把每個功能都交代清楚,更何況有些我從來沒用過。想深入了解或查詢特定功能的話,還是請多參考 help file 或 google。

數值運算

逐樣本點的運算

這段我會談到如何操作、生成變數。大部分 STATA 生成變數時都是對變數/欄位(們)做 item-wise 的操作:對 columns 逐 row/observation 內進行運算。最基本的用法是利用 gen <var> = <exp> 生成變數,以及利用 replace 來修改現有的變數。以下是一些說明與簡單的範例:

  • Expression <exp> 由變數和運算子組成,如: var^1+var^2*var^3)/100
  • gen total_score = micro + macro + stat ,將每個樣本點的三個變數:micro、macro、stat 加總並「生成」新變數 total_score。
  • replace GDP = C + I + G + EX — IM ,「更新」現有的變數 GDP 為加總消費、投資、政府支出、淨出口的運算組合。

除了常見的加減乘除與指數運算子外,STATA 也提供許多內建的函式,如 log()exp()sqrt() 等,這些也可以直接搭配使用於 <exp>。²

跨樣本點的彙整運算

然而有時候我們想生成的變數需要去彙整某個(些)變數的數筆樣本點,例如計算平均、 標準差、標準化或加總等。這和 item-wise 的操作不同,涉及到了跨樣本點的操作,這時候 egen 提供了相當多樣且方便的 aggregating function 可供使用³,以下條列幾個常用的 egen function:

  • egen <v1> = mean(<v2>):生成變數 <v1> 來記錄 <v2> 平均。其實呢,mean() 裡 面其實也可以是 <exp>,比如說 mean(<v2>/100 + <v3>)
  • egen <v1> = total(<logic exp>) :計算有多少樣本符合條件 <logic exp> (下段就會提到)。
  • egen <v1> = sum(<v2>) ,生成變數 <v1> 來記錄 <v2> 加總。⁴
  • egen <v1> = rowmax(<varlist>) ,生成變數 <v1> 來記錄 <varlist> 中的最大值,這邊的 <varlist> 是變數列表,如:score1 score2 score3 。有趣的是: rowmax() 並沒有像多數 egen functions 一樣,進行跨樣本點的運算。
利用 egen 標準化
Fig. 2–4 利用 egen 標準化

關於剛剛提到的標準化,Fig 2-4 提供了一個 egen 的作法。這邊我使用了mean()sd() 或是更直接的 std()。最後再補充一些和生成變數相關的實用指令與用法。

特殊運算:第幾筆、總筆數、切換變數類型

這邊要再補充一些特殊的變數生成方式,每個都是相當實用(我也會用在之後的範例中):

  • gen <var> = _n ,依照樣本排序給予從 1 開始的編號。
  • gen <var> = _N ,回傳總樣本數。
  • destring <var1>, gen(<var2>) ,將「字串」變數 var1 變成「數值」變數 var2。請注意,只有「看起來像數值」的字串變數可以進行轉換。此外,tostring 則可以進行反向操作。
  • encode <var1>, gen(<var2>) ,將字串變數轉成「類別化」的數值變數。

例 1、2 的 _n_N 是兩個有趣的表示法,分別反應第幾筆與總筆數。關於例 3、4,由於「字串」與「數值」變數各自只能進行特定的操作,我們很常需要先做轉換。另外,例 4 中的 encode 會將變數類別化(在 data browser 中呈藍字,我在 2–3 的類別標籤中還會再做些說明)。

邏輯條件

邏輯運算子
Fig 2–5 邏輯運算子

我們經常要依照條件做特定的操作。最常見的條件是由 if 開頭,再加上由變數、數值、運算子與邏輯運算子(see Fig 2-5)組成的 logic expression <logic_exp>。STATA 的邏輯運算子和許多程式的慣例一樣,而條件間也可以利用且 &、或 | 組合在一起。多了條件式後, 就能進行更多特定的操作。以下搭配前段提過的幾個指令舉例說明:

  • tab cred if female == 1 & dep == ”Econ” ,對變數 femaledep 為 “1”、”Econ” 的樣本做學分數 cred 的次數分佈。
  • replace grade = ”C-” if score > 50 & score <= 60 & makeup==1 ,將滿足條件的人,grade 改為 ”C-”。
  • gen old = 1 if age >= 80 & age < . ,對於 80 歲以上且年齡非遺失的人,生成變數 old 來標註老年。

有幾點需要留意。首先,請留意指定值(= assign)和等值(== equivalence)間的差異;其次,指定字串變數值時,需要加上 ”” (如 2–1中, Fig 2-2 輸入的字串值);最後,請先記得,數值資料的遺失值「.」在 STATA 中是被視為無限大。各位可以想想看,如果例 3 少掉 age < . 可能會發生什麼事。⁴

條件相關應用:丟資料、驗證、條件平均

除了在條件下生成或修改變數,條件式還有許多用途,如:篩選資料或檢查樣本點是否符合條件,也可以搭配 egen 計算條件平均及其他彙整函數,以下介紹一些指令與條件式的搭配:

  • drop if <logic exp> ,丟掉符合特定條件的樣本點。
  • gen <var> = (<logic exp>) ,生成符合條件的二元變數(符合為 1,不符合為 0)。
  • assert <logic exp> ,檢查條件是否成立。
  • egen <v1> = mean(<v2> / (<logic_exp>)) ,生成 <v2> 的條件平均數,條件為 <logic_exp>

首先,例1 中的 drop 除了丟掉特定樣本點外,也可以藉由 drop <varlist> 刪去特定變數。此外,指令 keep 的用法和 drop 一樣,只差在功能完全相反(看名字應該就能理解)。例 2 在生成作為 indicator 的二元變數時非常方便(當然,我們也可以分別寫 gen 、 replace),然而這樣的用法需要小心。具體來說,他生成的是「條件 A 與非 A」,但「非 A」有時候不一定是我們想要的,例如當條件 A 代表 18 歲以下時,「非 A」就會是「18 歲以上以及 missing」。例 3 在清理與檢查資料的過程非常實用。比如說,我們可以藉由 assert weight >= 0 & weight < . 檢查是否變數體重有負值與遺失值。最後,例 4 的條件運算非常好用,也可以應用於 mean() 以外的 egen function。事實上,例 4 mean() 裡面可以理解成一種 <exp>(參考上一段), 也就是將 <v2> 逐樣本點(item-wise)地除上 <logic_exp> 所代表的 二元變數,這麼做會讓不符合條件的樣本點被除上 0 並回傳 missing,由於 missing 值不會納入運算,藉此可以實現條件運算。⁵

[1]: 變數類型和儲存形式是不太一樣的概念,我在 5–2 會討論到 STATA 變數的儲存類型。

[2]: 更多 STATA 內間的數值運算可以參考官方文件

[3]: 這件事也可以透過敘述統計或資料彙整達成(see 3–2),但有時我們希望他在原資料中,直接以新的變數生成。如果是用過 SQL 的讀者,egen 差不多就是 Window Function。

[4]: 請注意,gen 也有 function sum() 但功能不相同。gen v1=sum(v2) 生成的是從第一筆樣本點到當前樣本點的累計加總(cumulative sum/rolling sum);egen v1=sum(v2) 生成的則是所有養本點的加總。

[5]: 如果資料中有人的 age 為 missing,他們會被錯誤地被標記為 old。

[6]: 另一個的用法是 mean(cond(<logic exp>,<v2>,<v3>)) :當條件成立時回傳 <v2>,不成立時則回傳 <v3>, 若把 <v3> 設成 missing 則等價於例 4 的用法。參考自 STATA Forum 的討論

--

--

CW Wayne Yeh

資料分析/閱讀筆記/生活雜感。我是葉政維,台大經研畢,目前是樹鋸分析師🪚,正在職場站穩腳步,也在探索什麼是好的生活。