R 包 `ezdf`的講解
作者簡介Introduction
數據匠(http://baidao.net):http://www.baidao.net/
往期回顧
談談R中的亂碼(一)談談R中的亂碼(二)談談R中的亂碼(三)目的
- 在導入 SPSS Stata 等格式時,提供統一的處理標籤的介面;
- 在輸出表格時提供對標籤的自動化處理;
什麼是標籤
SPSS 和 Stata 的用戶最熟悉標籤:
- 變數標籤
gender `性別`
age `年齡`
- 數值標籤
gender:
1 = 男性
2 = 女性
R 中如何處理標籤
首先,data.frame 沒有變數標籤的概念(attr 另外再說),變數名行使標籤的功能:
table(dt$`性別`)
# 如果標籤有空格table(dt$`a variable`)
其次,可用 factor 提供數值標籤功能(factor 其實就等價於字元型):
levels(df$`性別`) <- c(男, 女)
R 包對標籤的處理
通過對象屬性設置來保存標籤:
- foreign
attr(df, variable.labels) # 變數標籤
attr(var, value.labels) # 數值標籤
- haven
和 foreign 道理一樣,只不過命名方式不同。此外,haven 把變數標籤和數值標籤都作為變數的屬性,而在 foreign 中,變數標籤是 data.frame 的屬性,數值標籤才是變數的屬性。
attr(var, label)
attr(var, labels)
顯示在 RStudio 中是這樣的:
ezdf 提供統一的數據導入介面
- 對數據導入提供統一介面,封裝 foreign、haven 等包的導入函數;
- 修正一些 bug,例如:
`haven`: 「Error: `x` and `labels` must be same type」
導入 Stata 數據
導入 Stata 數據使用 readStata() 函數:
library(ezdf)
dat <- readStata(CGSS2013(居民問卷)發布版_2014.dta, encoding = GB2312) # View(dat) # 參數 `encoding` 設置 Stata 標籤的編碼,該參數默認值為 UTF-8。 # 有的 Stata 數據對變數名以及字元變數(string)的值都採用不同編碼,對於這種情況, # 需分別設置 `varNameEncoding` 和 `charEncoding`。 dat <- readStata(CGSS2013(居民問卷)發布版_2014.dta, encoding = GB2312, varNameEncoding = UTF-8, charEncodin = UTF-8)
導入 SPSS 數據
導入 SPSS 數據使用 readSPSS() 函數
# 參數 `lib` 設置導入所使用的 R 包,目前支持 `foreign` 和 `haven`。
readSPSS(file, lib = "foreign", ...)
將 data.frame 轉換為 ezdf
用 as.ez(dt, meta) 創建一個新的 ez.data.frame 對象
data(iris)
library(ezdf)d1 = as.ez(iris) class(d1) ## [1] "ez.data.frame" "data.table" "data.frame"
ezdf 對標籤的設置
變數標籤
- 變數標籤存儲在 meta 屬性當中;
- meta 可為 data.frame 或 matrix 類型對象:至少包括兩列:第一列為變數名,第二列為變數標籤。
兩個輔助函數:
- `setmeta()`
- `getmeta()`
d1$test = sample(5, size = nrow(iris), replace = T)
# 對新變數 test 設置變數標籤 setmeta(d1, data.frame(var= test, lbl = 這是新變數標籤))# 顯示數據 d1 的全部變數標籤 attr(d1, meta)
## var lbl ## 1: test 這是新變數標籤 # 或者 getmeta(d1) ## var lbl ## 1: test 這是新變數標籤varLabels(d1, c(Species, test)) ## [1] "" "這是新變數標籤" # 用 default = "var" 只輸出帶有標籤的變數 varLabels(d1, c(Species, test), default = "var")## [1] "Species" "這是新變數標籤"
# 返回所有已定義的變數標籤 varLabels(d1) ## var lbl ## 1: test 這是新變數標籤
單獨設置部分變數標籤
# 設置變數標籤
varLabels(d1, "test") <- "新標籤"varLabels(d1, "test")## [1] "新標籤"
數值標籤
數值標籤的存儲採用命名整數向量作為變數的 labels 屬性
# 定義一個數值標籤
c(C1 = 1, C2 = 2, C3 = 3, MI = 9)
- valueLabels()
vl1 = valueLabels(d1, test)
vl1## list() ## attr(,"class") ## [1] "value.labels" ## attr(,"ez") ## [1] "d1" ## attr(,"col") ## [1] "test"# 數值標籤可以「加減」。
# 注意: MI=9 設了一個不存在的值標籤 vl2 = vl1 + c("Class1"=1, "Class2"=2, "Class3"=3, Class4=4, Class5 = 5, MI = 9, MM = 8) valueLabels(d1, test) = vl2
製表函數
tbl()
tbl(d1, ~test)
## test 新標籤 N## 1: 1++Class1 25 ## 2: 2++Class2 37## 3: 3++Class3 23## 4: 4++Class4 25## 5: 5++Class5 40
# 分組求均值,添加樣本數
tbl(d1, Sepal.Length ~ Species + test, mean, N = T)
## Species test 新標籤 Sepal.Length N ## 1: setosa 1++Class1 5.141667 12 ## 2: setosa 2++Class2 4.923077 13 ## 3: setosa 3++Class3 5.200000 5 ## 4: setosa 4++Class4 5.044444 9 ## 5: setosa 5++Class5 4.836364 11 ## 6: versicolor 1++Class1 5.900000 4 ## 7: versicolor 2++Class2 5.941667 12## 8: versicolor 3++Class3 5.908333 12 ## 9: versicolor 4++Class4 6.142857 7 ## 10: versicolor 5++Class5 5.866667 15 ## 11: virginica 1++Class1 6.533333 9 ## 12: virginica 2++Class2 6.583333 12 ## 13: virginica 3++Class3 6.883333 6 ## 14: virginica 4++Class4 6.344444 9 ## 15: virginica 5++Class5 6.657143 14
# tbl() 默認按照公式右端 x 的值排序,如果取消排序
tbl(d1, Sepal.Length ~ Species + test, mean, N = T, sort = F)
## Species test 新標籤 Sepal.Length N ## 1: setosa 4++Class4 5.044444 9 ## 2: setosa 5++Class5 4.836364 11 ## 3: setosa 1++Class1 5.141667 12 ## 4: setosa 2++Class2 4.923077 13 ## 5: setosa 3++Class3 5.200000 5 ## 6: versicolor 4++Class4 6.142857 7 ## 7: versicolor 2++Class2 5.941667 12## 8: versicolor 5++Class5 5.866667 15 ## 9: versicolor 3++Class3 5.908333 12 ## 10: versicolor 1++Class1 5.900000 4 ## 11: virginica 4++Class4 6.344444 9 ## 12: virginica 5++Class5 6.657143 14 ## 13: virginica 2++Class2 6.583333 12 ## 14: virginica 1++Class1 6.533333 9 ## 15: virginica 3++Class3 6.883333 6
ctbl()
ctbl() 是對 table() 的封裝,採用 ctbl(ez, expr) 的調用方式。
ctbl(d1, Sepal.Length ~ Species + test)
# 等價於table(d1$Sepal.Length, d1$Species, d1$test)
ftable()
ftable.ez.data.frame() 方法是對 ftable() 的封裝
ftable(ez, formula, style = 1, prop_margin = 1, ...)
- prop_margin: 行百分比 / 列百分比;
- style = 1:輸出頻次;
- style = 2:輸出百分比;
- style = 3:輸出百分比和行加總頻次。
ftable(d1, Species~test)
## ## setosa versicolor virginica ## 1++Class1 12 4 9 ## 2++Class2 13 12 12 ## 3++Class3 5 12 6 ## 4++Class4 9 7 9 ## 5++Class5 11 15 14
ftable(d1, Species~test, style = 2)
##
## setosa versicolor virginica ## 1++Class1 0.4800000 0.1600000 0.3600000 ## 2++Class2 0.3513514 0.3243243 0.3243243## 3++Class3 0.2173913 0.5217391 0.2608696 ## 4++Class4 0.3600000 0.2800000 0.3600000 ## 5++Class5 0.2750000 0.3750000 0.3500000(t1 = ftable(d1, Species~test, style = 3))## setosa versicolor virginica N ## 1++Class1 0.4800000 0.1600000 0.3600000 25 ## 2++Class2 0.3513514 0.3243243 0.3243243 37 ## 3++Class3 0.2173913 0.5217391 0.2608696 23 ## 4++Class4 0.3600000 0.2800000 0.3600000 25 ## 5++Class5 0.2750000 0.3750000 0.3500000 40
與 markdown 流程整合
- pander 是用於 markdown 格式輸出的 R 包,提供了非常豐富的表格輸出功能
- 在載入 ezdf 包之後,會自動與 pander 包結合,實現自動標籤輸出
# pander 輸出
library(pander) pander(t1, ez = d1)
這是輸出的 markdown 結果:
----------------------------------------------------
setosa versicolor virginica N
--------------- -------- ------------ ----------- ---
**1++Class1** 0.48 0.16 0.36 25
**2++Class2** 0.3514 0.3243 0.3243 37
**3++Class3** 0.2174 0.5217 0.2609 23
**4++Class4** 0.36 0.28 0.36 25
**5++Class5** 0.275 0.375 0.35 40
-----------------------------------------------------
最終輸出效果:
pander 與回歸結果輸出:
# 加上數值標籤
options(ezdfKeepVal = T)pander(tbl(dat, a66 ~ s5a, mean))
---------------------------------------------------------
s5a 受訪者居住的地區類型是 a66 您家是否擁有家用小汽車
---------------------------- ----------------------------
1++市/縣城的中心地區 1.761
2++市/縣城的邊緣地區 1.775
3++市/縣城的城鄉結合部 1.809
4++市/縣城區以外的鎮 1.859
5++農村 1.919
---------------------------------------------------------
數值與標籤之間分隔符
options(ezdfValueLabelSep = =)
pander(tbl(dat, a66 ~ s5a, mean))
---------------------------------------------------------
s5a 受訪者居住的地區類型是 a66 您家是否擁有家用小汽車
---------------------------- ----------------------------
1=市/縣城的中心地區 1.761
2=市/縣城的邊緣地區 1.775
3=市/縣城的城鄉結合部 1.809
4=市/縣城區以外的鎮 1.859
5=農村 1.919
---------------------------------------------------------
回歸模型的輸出:
m1 = lm(a6 ~ a2 + a10, dat)
pander(m1)
這是通過 markdown 輸出轉成 pdf 後的效果,沒有任何手工干預(pandoc 在輸出小數點時,還有一點瑕疵,比如小數點位數不統一,不過本人 github 上的版本已經修正了這個問題)。
表格輸出選項
目前提供三個選項:
- options(ezdfKeepVal = T)
- options(ezdfValueLabelSep = =)
- options(ezdfKeepVarName = T)
options(ezdfKeepVal = T)
options(ezdfValueLabelSep = =) options(ezdfKeepVarName = F) tbl(d1, ~test) ## 新標籤 N ## 1: 1=Class1 25 ## 2: 2=Class2 37 ## 3: 3=Class3 23 ## 4: 4=Class4 25 ## 5: 5=Class5 40 pander(tbl(d1, ~test))
options(ezdfKeepVarName = T)
options(ezdfValueLabelSep = ++) pander(tbl(d1, ~test))
下載與安裝
github:
huashan/ezdf往期精彩內容整理合集
2017年R語言發展報告(國內)R語言中文社區歷史文章整理(作者篇)R語言中文社區歷史文章整理(類型篇)推薦閱讀: