R中变量标签管理
👇 连享会 · 推文导航 | www.lianxh.cn
🍎 Stata:Stata基础 | Stata绘图 | Stata程序 | Stata新命令 📘 论文:数据处理 | 结果输出 | 论文写作 | 数据分享 💹 计量:回归分析 | 交乘项-调节 | IV-GMM | 时间序列 | 面板数据 | 空间计量 | Probit-Logit | 分位数回归 ⛳ 专题:SFA-DEA | 生存分析 | 爬虫 | 机器学习 | 文本分析 🔃 因果:DID | RDD | 因果推断 | 合成控制法 | PSM-Matching 🔨 工具:工具软件 | Markdown | Python-R-Stata 🎧 课程:公开课-直播 | 计量专题 | 关于连享会
连享会课程 · 2023 五一论文班
作者:陈卓然 (中山大学)
邮箱:chenzhr25@mail2.sysu.edu.cn
温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:
目录
1. 引言
2. expss 包
2.1 设置变量和值标签
2.2 基础 R 和 ggplot2 中的函数使用标签
3. Labelled 包
3.1 值标签
3.2 对值标签进行排序
3.3 将其他值转化为 NA
3.4 转化为一个因子变量
3.5 有条件地转化为因子变量
4. 相关推文
1. 引言
变量标签是一个变量的详细名字,尽管 R 中可以将变量的名字取得非常长,甚至名字中可以包含空格和标点,但是短小的名字更容易进行编程。此时一个能够对变量进行一个非常漂亮而且详尽的描述的变量标签便显得极为重要了。通过这样的变量标签,我们可以非常容易地记住一个变量的名字指代的是什么。
值标签和变量标签类似。但是值标签指的是对一个变量可能的取值进行的详尽描述,将一个类别变量的取值进行标记的好处在于我们不再需要记忆诸如 1=Extremely poor
或者 7=Excellent
之类的含义了,因而我们可以很容易地通过 info
得到数据集的描述性分析和变量的描述性统计。
一般而言,将数值型数据和 R 中的标签关联起来的是因子变量,然而因子变量只能允许整数映射到一个文字标签当中,而这些整数必须是以 1 开始的,同时每一个值都必须有一个标签。同样,我们不能对因子变量计算均值或者其他的统计量。
通过标签我们能够在编程的时候使用短小的变量名字,而在结果输出的表格中我们能够看到文字版本的标签,这样对于结果的可视性有着非常大的帮助。
尽管在 R 中将标签作为变量的属性进行存储是一件非常方便的事情,但是绝大多数的 R 包并不能使用这些标签,甚至是删除这些标签。本文将要介绍的两个包:第一个包是 expss
,它能够将值标签整合到 R 中的基础函数和其他包中的函数中,其中的函数 use_labels
能够很大程度上简化变量标签的使用;第二个包是 labelled
。
2. expss 包
2.1 设置变量和值标签
首先我们可以将变量的标签添加到一个数据集中,如:
library(expss)
data(mtcars)
mtcars = apply_labels(mtcars,
mpg = "Miles/(US) gallon",
cyl = "Number of cylinders",
disp = "Displacement (cu.in.)",
hp = "Gross horsepower",
drat = "Rear axle ratio",
wt = "Weight (1000 lbs)",
qsec = "1/4 mile time",
vs = "Engine",
vs = c("V-engine" = 0,
"Straight engine" = 1),
am = "Transmission",
am = c("Automatic" = 0,
"Manual"=1),
gear = "Number of forward gears",
carb = "Number of carburetors"
)
除了 apply_labels
命令,我们还可以使用 var_lab
和 val_lab
的函数:
nps = c(-1, 0, 1, 1, 0, 1, 1, -1)
var_lab(nps) = "Net promoter score"
val_lab(nps) = num_lab("
-1 Detractors
0 Neutralists
1 Promoters
")
我们也可以读取、添加和移除现存的标签:
var_lab(nps) # get variable label
val_lab(nps) # get value labels
# add new labels
add_val_lab(nps) = num_lab("
98 Other
99 Hard to say
")
# remove label by value
# %d% - diff, %n_d% - names diff
val_lab(nps) = val_lab(nps) %d% 98
# or, remove value by name
val_lab(nps) = val_lab(nps) %n_d% "Other"
除此之外,也有很多很有用的函数可以直接作用于整个数据集,比如:
> drop_val_labs(nps)
LABEL: Net promoter score
VALUES:
-1, 0, 1, 1, 0, 1, 1, -1
> drop_var_labs(nps)
VALUES:
-1, 0, 1, 1, 0, 1, 1, -1
VALUE LABELS:
-1 Detractors
0 Neutralists
1 Promoters
99 Hard to say
> unlab(nps)
[1] -1 0 1 1 0 1 1 -1
> drop_unused_labels(nps)
LABEL: Net promoter score
VALUES:
-1, 0, 1, 1, 0, 1, 1, -1
VALUE LABELS:
-1 Detractors
0 Neutralists
1 Promoters
2.2 基础 R 和 ggplot2 中的函数使用标签
R 中的基础函数 table
中使用标签:
with(mtcars, table(am, vs))
绘制柱状图:
with(mtcars,
barplot(
table(am, vs),
beside = TRUE,
legend = TRUE)
)
对于处理数据框类型的函数而言,我们可以使用 use_labels
这一函数:
> use_labels(mtcars, table(am, vs))
Engine
Transmission V-engine Straight engine
Automatic 12 7
Manual 6 7
> use_labels(mtcars, lm(mpg ~ wt + hp + qsec)) %>% summary
Call:
lm(formula = `Miles/(US) gallon` ~ `Weight (1000 lbs)`
+ `Gross horsepower` + `1/4 mile time`)
Residuals:
LABEL: Miles/(US) gallon
VALUES:
-3.8591, -1.6418, -0.4636, 1.194, 5.6092
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 27.61053 8.41993 3.279 0.00278 **
`Weight (1000 lbs)` -4.35880 0.75270 -5.791 3.22e-06 ***
`Gross horsepower` -0.01782 0.01498 -1.190 0.24418
`1/4 mile time` 0.51083 0.43922 1.163 0.25463
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.578 on 28 degrees of freedom
Multiple R-squared: 0.8348, Adjusted R-squared: 0.8171
F-statistic: 47.15 on 3 and 28 DF, p-value: 4.506e-11
# boxplot with variable labels
use_labels(mtcars, boxplot(mpg ~ am))
最后我们可以在 ggplot2
中绘制带有变量标签和值标签的图,但是注意在使用之前我们需要使用 facet_grid
公式将标签变量转变为因子变量:
library(ggplot2, warn.conflicts = FALSE)
use_labels(mtcars, {
# '..data' is shortcut for all 'mtcars' data.frame inside expression
ggplot(..data) +
geom_point(aes(y = mpg, x = wt, color = qsec)) +
facet_grid(factor(am) ~ factor(vs))
})
3. Labelled 包
在 labelled
包中,我们可以通过 var_label()
来指定一个变量的标签:
library(labelled)
var_label(iris$Sepal.Length) <- "Length of sepal"
我们也可以通过使用一个名字列表给一个数据库中的多个变量添加标签,如:
var_label(iris) <- list(Petal.Length = "Length of petal", Petal.Width = "Width of Petal")
为得到变量标签,我们只需使用 var_label
:
var_label(iris$Petal.Width)
或者
var_label(iris)
为了移除一个变量的标签,我们可以使用 NULL
:
var_label(iris$Sepal.Length) <- NULL
你可以通过 look_for()
的命令来展示和搜寻变量名和标签,比如:
> look_for(iris)
pos variable label col_type values
1 Sepal.Length — dbl
2 Sepal.Width — dbl
3 Petal.Length Length of petal dbl
4 Petal.Width Width of Petal dbl
5 Species — fct setosa
versicolor
virginica
> look_for(iris,'pet')
pos variable label col_type values
3 Petal.Length Length of petal dbl
4 Petal.Width Width of Petal dbl
> look_for(iris, details = FALSE)
pos variable label
1 Sepal.Length —
2 Sepal.Width —
3 Petal.Length Length of petal
4 Petal.Width Width of Petal
5 Species —
3.1 值标签
第一种创建标签向量的方式是使用 labelled()
函数,这一函数的优势在于你不必为向量中的每一个值都赋予一个标签,同时你也可以为那些没有被观测到的值提供标签。比如:
> v <- labelled(c(1,2,2,2,3,9,1,3,2,NA), c(yes = 1, no = 3, "don't know" = 8, refused = 9))
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 no
8 don't know
9 refused
通过使用 var_labels()
来得到所有的值标签,使用 val_label()
来得到特定值的值标签:
> val_labels(v)
yes no don't know refused
1 3 8 9
> val_label(v,8)
[1] "don't know"
val_labels()
也可以用来修正一个变量的所有的值标签,而相比之下 val_label()
只能更新某一个特定的值标签,例如:
> val_labels(v) <- c(yes = 1, nno = 3, bug = 5)
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 nno
5 bug
> val_label(v, 3) <- "no"
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 no
5 bug
通过使用 val_label()
你也可以添加或者移除某一特定的值标签。
> val_label(v, 2) <- "maybe"
> val_label(v, 5) <- NULL
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 no
2 maybe
我们也可以将 val_labels()
应用于一个数据框中的一些列。
> df <- data.frame(v1 = 1:3, v2 = c(2, 3, 1), v3 = 3:1)
> val_label(df, 1) <- "yes"
> val_label(df[, c("v1", "v3")], 2) <- "maybe"
> val_label(df[, c("v2", "v3")], 3) <- "no"
> val_labels(df)
$v1
yes maybe
1 2
$v2
yes no
1 3
$v3
yes maybe no
1 2 3
> val_labels(df[, c("v1", "v3")]) <- c(YES = 1, MAYBE = 2, NO = 3)
> val_labels(df)
$v1
YES MAYBE NO
1 2 3
$v2
yes no
1 3
$v3
YES MAYBE NO
1 2 3
> val_labels(df) <- list(v1 = c(yes = 1, no = 3), v2 = c(a = 1, b = 2, c = 3))
> val_labels(df)
$v1
yes no
1 3
$v2
a b c
1 2 3
$v3
YES MAYBE NO
1 2 3
3.2 对值标签进行排序
值标签默认是按照他们被创建的顺序进行排列的。
> v <- c(1,2,2,2,3,9,1,3,2,NA)
> val_label(v, 1) <- "yes"
> val_label(v, 3) <- "no"
> val_label(v, 9) <- "refused"
> val_label(v, 2) <- "maybe"
> val_label(v, 8) <- "don't know"
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 no
9 refused
2 maybe
8 don't know
但是有时或许需要对其进行重新的排序,比如说:
> sort_val_labels(v)
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
2 maybe
3 no
8 don't know
9 refused
> sort_val_labels(v)
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
2 maybe
3 no
8 don't know
9 refused
> sort_val_labels(v, decreasing = TRUE)
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
9 refused
8 don't know
3 no
2 maybe
1 yes
> sort_val_labels(v, according_to = "l")
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
8 don't know
2 maybe
3 no
9 refused
1 yes
3.3 将其他值转化为 NA
在一些情况下,没有对应的值标签的值可能会被视为缺失值,为此我们需要将其转为 NA
:
> v <- labelled(c(1,2,2,2,3,9,1,3,2,NA), c(yes = 1, maybe = 2, no = 3))
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
2 maybe
3 no
> nolabel_to_na(v)
<labelled<double>[10]>
[1] 1 2 2 2 3 NA 1 3 2 NA
Labels:
value label
1 yes
2 maybe
3 no
有时也有可能一个值标签对应一个缺失值,我们可以根据这个值标签挑出缺失值:
> size <- labelled(c(1.88, 1.62, 1.78, 99, 1.91), c("not measured" = 99))
> size
<labelled<double>[5]>
[1] 1.88 1.62 1.78 99.00 1.91
Labels:
value label
99 not measured
> val_labels_to_na(size)
[1] 1.88 1.62 1.78 NA 1.91
3.4 转化为一个因子变量
一个带有标签的向量可以被转化为一个因子变量,通过使用 to_factor()
,例如:
> v <- labelled(c(1,2,2,2,3,9,1,3,2,NA), c(yes = 1, no = 3,
"don't know" = 8, refused = 9))
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 no
8 don't know
9 refused
> to_factor(v)
[1] yes 2 2 2 no refused yes no 2 <NA>
Levels: yes 2 no don't know refused
我们可以通过 levels
这一个参数来指明什么应该被作为因子水平,默认情况下是将标签 labels
作为因子水平,也可以将值作为因子水平或者是以值为前缀的标签作为因子水平,如:
> to_factor(v)
[1] yes 2 2 2 no refused yes no 2 <NA>
Levels: yes 2 no don't know refused
> to_factor(v)
[1] yes 2 2 2 no refused yes no 2 <NA>
Levels: yes 2 no don't know refused
> to_factor(v, levels = "v")
[1] 1 2 2 2 3 9 1 3 2 <NA>
Levels: 1 2 3 8 9
> to_factor(v,levels = "p")
[1] [1] yes [2] 2 [2] 2 [2] 2 [3] no [9] refused [1] yes [3] no
[9] [2] 2 <NA>
Levels: [1] yes [2] 2 [3] no [8] don't know [9] refused
此外我们也可以加入参数 ordered
来创建一个有序因子变量:
> to_factor(v, ordered = TRUE)
[1] yes 2 2 2 no refused yes no 2 <NA>
Levels: yes < 2 < no < don't know < refused
我们也可以加入参数 nolabel_to_na
来指明是否在转为因子变量之前是否需要应用一个函数。因此如下的两条命令是等价的:
> to_factor(nolabel_to_na(v))
[1] yes <NA> <NA> <NA> no refused yes no <NA> <NA>
Levels: yes no don't know refused
> to_factor(v,nolabel_to_na = TRUE)
[1] yes <NA> <NA> <NA> no refused yes no <NA> <NA>
Levels: yes no don't know refused
另外一个非常有用的参数是 sorted_levels
,这一参数可以用来指明因子水平应该以何种方式进行排序:其中 none
表示按照值的大小进行排序,labels
表示按照标签排序
> to_factor(v, sort_levels = "n")
[1] yes 2 2 2 no refused yes no 2 <NA>
Levels: yes no don't know refused 2
> to_factor(v, sort_levels = "l")
[1] yes 2 2 2 no refused yes no 2 <NA>
Levels: 2 don't know no refused yes
我们也可以使用函数 to_labelled()
来将一个因子变量转化为一个带有标签的数值向量。
> f <- factor(1:3, labels = c("a", "b", "c"))
> f
[1] a b c
Levels: a b c
> to_labelled(f)
<labelled<double>[3]>
[1] 1 2 3
Labels:
value label
1 a
2 b
3 c
但是需要注意的是,to_labelled(to_factor(v))
并不等价于 v
:
> v
<labelled<double>[10]>
[1] 1 2 2 2 3 9 1 3 2 NA
Labels:
value label
1 yes
3 no
8 don't know
9 refused
> to_labelled(to_factor(v))
<labelled<double>[10]>
[1] 1 2 2 2 3 5 1 3 2 NA
Labels:
value label
1 yes
2 2
3 no
4 don't know
5 refused
3.5 有条件地转化为因子变量
为了便于分析,研究者有时需要识别那些带有标签的数值变量是类别型变量 (因此需要使用 to_factor()
将其转化为因子),或者是连续变量 (因子需要对其使用 base::unclass()
)。需要注意的是绝大多数函数 (包括绝大多数的回归函数和绘图函数如 ggplot2
都需要将类别变量设置为因子变量),为此你需要使用 unlabelled()
来完成这一转变。
> df <- data.frame(
+ a = labelled(c(1, 1, 2, 3), labels = c(No = 1, Yes = 2)),
+ b = labelled(c(1, 1, 2, 3), labels = c(No = 1, Yes = 2, DK = 3)),
+ c = labelled(c(1, 1, 2, 2), labels = c(No = 1, Yes = 2, DK = 3)),
+ d = labelled(c("a", "a", "b", "c"), labels = c(No = "a", Yes = "b")),
+ e = labelled_spss(
+ c(1, 9, 1, 2),
+ labels = c(No = 1, Yes = 2),
+ na_values = 9
+ )
+ )
> df %>% look_for()
pos variable label col_type values
1 a — dbl+lbl [1] No
[2] Yes
2 b — dbl+lbl [1] No
[2] Yes
[3] DK
3 c — dbl+lbl [1] No
[2] Yes
[3] DK
4 d — chr+lbl [a] No
[b] Yes
5 e — dbl+lbl [1] No
[2] Yes
> unlabelled(df)%>% look_for()
pos variable label col_type values
1 a — dbl
2 b — fct No
Yes
DK
3 c — fct No
Yes
DK
4 d — chr
5 e — fct No
Yes
4. 相关推文
Note:产生如下推文列表的 Stata 命令为:
lianxh r语言, m
安装最新版lianxh
命令:
ssc install lianxh, replace
专题:Stata命令 Stata与R语言等价命令 专题:倍分法DID 如何在R语言中实现多期DID 专题:Python-R-Matlab R语言随机指数图分析-statnet R语言绘制社会网络图
New! Stata 搜索神器:
lianxh
和songbl
GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
. ssc install lianxh
. ssc install songbl
👉 使用:
. lianxh DID 倍分法
. songbl all
🍏 关于我们
连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。