R读入和处理SPSS、stata中文CGSS数据

文章目录

R能够读入和处理SPSS和stata数据,但是R中因子型变量(factor变量,也就是分类变量)是数值变量和文本变量之外的一种单独的类型。而R会对不同的类型对象采取不同的处理方法,从而具有其他的优势,如因子变量放在回归模型中会自动作为虚拟变量。

在SPSS和Stata数据中,实际上只存在两类变量,数值变量和文本变量,分类变量实际上只是带有标签的数值变量。你要他们相互加减乘除,机器也是可以做的,阻止如此做的是人,但是在R中让两个分类变量相加是不行的。

因此,为了发挥R的独特优势,我们读入stata和spss数据时,应该将spss和stata中带有标签的分类变量都转化为因子变量。但是这两个数据不仅仅会给分类变量加标签,还会给连续数值变量加上用户缺失值标签。

那么如何处理这两类不同的标签呢?一种是不区分,统一读进来,将标签信息保存起来,读进来的数据为一种特殊类型的变量。一种是读的时候就区分,全部取值都带来有标签的转变为因子,而标签不全的变量保留标签信息但是不转变为因子。

haven包和sj在haven基础上改进开发的sjmisc包采用的是前一种处理思路,读进来的变量为labelled类型,变量标签和取值标签保存在变量的相关属性中。sjlabelled、sjPlot、sjstat等包可以调用,也可以通过设定好的函数依据标签转化为因子变量。

而foreign包和readstata13包采用的是第二种处理思路。在读入数据时可以通过一定的设定将带标签的分类变量转变为因子,而带用户缺失值标签的连续变量(标签不全的变量)仍然保持数值变量类型,但保留了取值标签信息,备查。

R还可以写出SPSS和Stata格式的数据。因此,当你只有某个较新版本的spss或者stata数据,而手头的软件版本比较低时,要读入新版本的数据时,除了让有新版本软件的朋友帮你另存为旧版本的数据,或者使用statransfor之外,一种方法就是用开源的R读入新版本的数据,然后写出成为旧版本的数据。本文暂时不讨论。
本文不全,全文github版本在:https://github.com/lidingruc/2017R/blob/master/lesson5/lesson5H.Rmd

一、haven包读入SPSS、stata或SAS数据

Rstudio推荐使用haven包读入数据

library(haven)
data1 <- read_sav("路径+文件名.sav")
data2 <- read_stata("路径+文件名.dta",encoding ="GB2312")
data3 <- read_sas("路径+文件名.sas7bdat")

haven包读人SPSS和Stata数据后,变量和取值标签变为变量的属性,变量默认为labelled类型。

Stata14之前的数据未存Encoding信息,需设定中文数据可能是GB2312编码。

SPSS数据和Stata14后版本支持unicode编码。haven可默认读入。

1.1 读Stata数据

当预览标签为乱码时,可尝试设定encoding=“GB2312”或者encoding=“gbk”。预览没有乱码时,意味着这数据encoding为默认的utf-8。

library(haven)
cgss2003 <- read_dta("cgss2003.dta",encoding = "utf-8")
str(cgss2003$sitetype)
## Class 'labelled'  atomic [1:5894] 1 1 1 1 1 1 1 1 1 1 ...
##   ..- attr(*, "label")= chr "调查地类型"
##   ..- attr(*, "format.stata")= chr "%31.0g"
##   ..- attr(*, "labels")= Named num [1:7] -3 -2 -1 1 2 3 4
##   .. ..- attr(*, "names")= chr [1:7] "不适合" "无填答/不回答" "不知道/说不清" "直辖市/省会城市的市区" ...
attr(cgss2003$sitetype,"label")
## [1] "调查地类型"
attr(cgss2003$sitetype,"labels")
##                不适合         无填答/不回答         不知道/说不清 
##                    -3                    -2                    -1 
## 直辖市/省会城市的市区            地级市市区              县城城区 
##                     1                     2                     3 
##                  集镇 
##                     4

1.2 读入SPSS数据

SPSS数据默认unicode编码,haven包的read_spss不能设定encoding信息。如果预览中spss数据标签等内容存在乱码,原数据的编码不一致,可以另存为低版本的spss统一编码形式然后haven读入或者使用后面的foreign包读入spss数据,它可以设定编码格式。

1.3 查看读入SPSS &Stata数据后的label信息

haven包默认导入spss和stata数据后,变量标签存在变量的的label属性当中,取值标签在labels属性当中。

library(tidyverse)
## Loading tidyverse: ggplot2
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag():    dplyr, stats
library(haven)
cgss2003 <- read_sav("CGSS2003b.sav")  # spss7.0版数据
str(cgss2003$sitetype)
## Class 'labelled'  atomic [1:5894] 1 1 1 1 1 1 1 1 1 1 ...
##   ..- attr(*, "label")= chr "调查地类型"
##   ..- attr(*, "format.spss")= chr "F2.0"
##   ..- attr(*, "labels")= Named num [1:7] -3 -2 -1 1 2 3 4
##   .. ..- attr(*, "names")= chr [1:7] "不适合" "无填答/不回答" "不知道/说不清" "直辖市/省会城市的市区" ...
attr(cgss2003$sitetype,"label")
## [1] "调查地类型"
attr(cgss2003$sitetype,"labels")
##                不适合         无填答/不回答         不知道/说不清 
##                    -3                    -2                    -1 
## 直辖市/省会城市的市区            地级市市区              县城城区 
##                     1                     2                     3 
##                  集镇 
##                     4

1.4 使用label信息

这些标签信息怎么使用呢?如果直接统计分析,输出中没有标签信息

cgss2003 %>%  count(sitetype)
## # A tibble: 5 x 2
##    sitetype     n
##   <dbl+lbl> <int>
## 1        -2     1
## 2         1  2325
## 3         2  1527
## 4         3  1299
## 5         4   742
ggplot(cgss2003, aes(x=sitetype)) +
  geom_bar() + 
  scale_x_discrete(drop=TRUE)

1.5 使用label信息:使用sjPlot包分析

Daniel Lüdecke 专门研究了如何使用spss和stata数据导入附带的label信息,创建了一系列的包,并将之tidyverse化。

#if(!require(sjmisc)) install.packages("sjmisc")
if(!require(sjPlot)) install.packages("sjPlot")
sjt.frq(cgss2003$sitetype)
调查地类型
value N raw % valid % cumulative %
无填答/不回答 1 0.02 0.02 0.02
直辖市/省会城市的市区 2325 39.45 39.45 39.46
地级市市区 1527 25.91 25.91 65.37
县城城区 1299 22.04 22.04 87.41
集镇 742 12.59 12.59 100.00
missings 0 0.00
total N=5894 · valid N=5894 · x̄=2.08 · σ=1.06
sjp.setTheme(theme.font ='STXihei' ) # STHeiti也可
cgss2003  %>% select(sitetype) %>%  sjplot(fun="frq")

Daniel开发的 sjlabelled包中还有一些专门处理标签信息的函数,例如获得标签

sjlabelled::get_labels(cgss2003$sitetype,include.values="n")

sjlabelled::set_labels(cgss2003$sitetype,
                       labels=c("不适合"="-3",
                                "无填答/不回答"="-2",
                                "不知道/说不清" = "-1",
                                "直辖市/省会城市的市区" = "1",
                                "地级市市区"  ="2",
                                "县城城区"="3" ,
                                "集镇" ="4" ))

mac中使用sjp中的作图函数绘制图形时,注意设定好字体,只有支持中文的字体才能在图形的标签元素(如标题)中呈现出来,如果是几何元素对应的标签,也需要设定,参见下面的解决方案。

sjp更多介绍1;

sjp更多介绍2;

MAC电脑Rstudio作图中文乱码的解决方案

可以用的中文字体名列表

1.6 使用label信息:将labelled分类变量转换为因子

使用haven包的as_factor()命令可以将labelled类型的变量变成因子,将变量的取值替换为标签本身。这是R数据处理分类变量的普遍方式。方式如下:

cgss2003  %>%
  filter(sitetype>0) %>%
  select(sitetype) %>% 
  haven::as_factor() %>% 
  droplevels() %>% 
  sjplot(fun="frq",axis.title="调查地类型")