为多个标记变量设置缺失值
set missing values for multiple labelled variables
如何为数据框中的多个标记向量设置缺失值。我正在使用来自 spss 的调查数据集。我正在处理大约 20 个不同的变量,它们具有相同的缺失值。所以想找到一种方法来使用 lapply() 来完成这项工作,但我做不到。
我实际上可以通过 as.numeric() 和 recode() 使用 base R 来做到这一点,但我对 haven 和标记的 class 的可能性很感兴趣,所以我想在 Hadley 的 tidyverse
中找到一种方法来完成这一切
感兴趣的变量大致如下所示。如果这是一个基本问题,我很抱歉,但我发现与 haven 和标签包相关的帮助文档非常无用。
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
lapply(v3, function(x) set_na_values(x, c(5,6)))
不太确定这是否是您要查找的内容:
v1 <- labelled(c(1, 2, 2, 2, 5, 6), c(agree = 1, disagree = 2, dk = 5, refused = 6))
v2 <- labelled(c(1, 2, 2, 2, 5, 6), c(agree = 1, disagree = 2, dk = 5, refused = 6))
v3 <- data_frame(v1 = v1, v2 = v2)
lapply(names(v3), FUN = function(x) {
na_values(v3[[x]]) <<- 5:6
})
lapply(v3, na_values)
返回最后一行
$v1
[1] 5 6
$v2
[1] 5 6
验证缺失值:
is.na(v3$v1)
[1] FALSE FALSE FALSE FALSE TRUE TRUE
这是正确的吗?
#Using replace to substitute 5 and 6 in v3 with NA
data.frame(lapply(v3, function(a) replace(x = a, list = a %in% c(5,6), values = NA)))
# x x.1
#1 1 1
#2 2 2
#3 2 2
#4 2 2
#5 NA NA
#6 NA NA
我知道 labelled_spss 允许您指定 na_range
甚至 na_values
的向量
#DATA
v11 = labelled_spss(x = c(1,2,2,2,5,6),
labels = c(agree=1, disagree=2, dk=5, refused=6),
na_range = 5:6)
#Check if v11 has NA values
is.na(v11)
#[1] FALSE FALSE FALSE FALSE TRUE TRUE
v22 = labelled_spss(x = c(1,2,2,2,5,6),
labels = c(agree=1, disagree=2, dk=5, refused=6),
na_range = 5:6)
#Put v11 and v22 in a list
v33 = list(v11, v22)
#Use replace like above
data.frame(lapply(X = v33, FUN = function(a) replace(x = a, list = is.na(a), values = NA)))
# x x.1
#1 1 1
#2 2 2
#3 2 2
#4 2 2
#5 NA NA
#6 NA NA
好的,我想我现在明白你想做什么了...
即在不删除基础导入数据的情况下将标签和值标记为 NA...
请参阅附录以获取更详细的示例,该示例使用 public 数据文件来显示利用 dplyr
更新多个列、标签的示例。 ..
建议的解决方案
df <- data_frame(s1 = c(1,2,2,2,5,6), s2 = c(1,2,2,2,5,6)) %>%
set_value_labels(s1 = c(agree=1, disagree=2, dk=5, refused=6),
s2 = c(agree=1, disagree=2, dk = tagged_na("5"), refused = tagged_na("6"))) %>%
set_na_values(s2 = c(5,6))
val_labels(df)
is.na(df$s1)
is.na(df$s2)
df
求解结果:
> library(haven)
> library(labelled)
> library(dplyr)
> df <- data_frame(s1 = c(1,2,2,2,5,6), s2 = c(1,2,2,2,5,6)) %>%
+ set_value_labels(s1 = c(agree=1, disagree=2, dk=5, refused=6),
+ s2 = c(agree=1, disagree=2, dk = tagged_na("5"), refused = tagged_na("6"))) %>%
+ set_na_values(s2 = c(5,6))
> val_labels(df)
$s1
agree disagree dk refused
1 2 5 6
$s2
agree disagree dk refused
1 2 NA NA
> is.na(df$s1)
[1] FALSE FALSE FALSE FALSE FALSE FALSE
> is.na(df$s2)
[1] FALSE FALSE FALSE FALSE TRUE TRUE
> df
# A tibble: 6 × 2
s1 s2
<dbl+lbl> <dbl+lbl>
1 1 1
2 2 2
3 2 2
4 2 2
5 5 5
6 6 6
现在我们可以操作数据了
mean(df$s1, na.rm = TRUE)
mean(df$s2, na.rm = TRUE)
> mean(df$s1, na.rm = TRUE)
[1] 3
> mean(df$s2, na.rm = TRUE)
[1] 1.75
使用Labeled package去除标签并替换为R NA
如果您希望去除标签并替换为 R NA 值,您可以使用 remove_labels(x, user_na_to_na = TRUE)
示例:
df <- remove_labels(df, user_na_to_na = TRUE)
df
结果:
> df <- remove_labels(df, user_na_to_na = TRUE)
> df
# A tibble: 6 × 2
s1 s2
<dbl> <dbl>
1 1 1
2 2 2
3 2 2
4 2 2
5 5 NA
6 6 NA
--
SPSS 格式说明/概述:
IBM SPSS(应用程序)可以以多种格式和非矩形配置导入和导出数据;但是,数据集总是被转换为 SPSS 矩形数据文件,称为系统文件(使用扩展名 *.sav)。变量格式、缺失值以及变量和值标签等元数据(有关数据的信息)与数据集一起存储。
价值标签
Base R 有一种数据类型可以有效地维护整数和字符标签之间的映射:因子。然而,这并不是因子的主要用途:它们被设计为自动为线性模型生成有用的对比。因素在重要方面与其他工具提供的标记值不同:
SPSS 和 SAS 可以标记数值和字符值,而不仅仅是整数值。
缺失值
这三个工具(SPSS、SAS、Stata)都提供了一个全局的“系统缺失值”,显示为.
。这大致等同于 R 的 NA
,尽管 Stata 和 SAS 都不会在数值比较中传播缺失值:SAS 将缺失值视为可能的最小数字(即 -inf),而 Stata 将其视为可能的最大数字(即inf).
每个工具还提供了一种记录多种缺失类型的机制:
- Stata 具有“扩展的”缺失值,.A 到 .Z。
- SAS 具有“特殊”缺失值,.A 到 .Z 加上 ._.
- SPSS 有每列“用户”缺失值。每列最多可以声明三个不同的值或一系列应视为缺失的值(加上一个不同的值)。
用户定义的缺失值
SPSS 的用户定义值与 SAS 和 Stata 的工作方式不同。每列可以有最多三个被视为缺失的不同值或一个范围。 Haven
提供 labelled_spss()
作为 labelled()
的子类来模拟这些额外的用户定义缺失。
x1 <- labelled_spss(c(1:10, 99), c(Missing = 99), na_value = 99)
x2 <- labelled_spss(c(1:10, 99), c(Missing = 99), na_range = c(90, Inf))
x1
#> <Labelled SPSS double>
#> [1] 1 2 3 4 5 6 7 8 9 10 99
#> Missing values: 99
#>
#> Labels:
#> value label
#> 99 Missing
x2
#> <Labelled SPSS double>
#> [1] 1 2 3 4 5 6 7 8 9 10 99
#> Missing range: [90, Inf]
#>
#> Labels:
#> value label
#> 99 Missing
标记缺失值
为了支持 Stata 的扩展和 SAS 的特殊缺失值,haven 实现了标记的 NA。它通过利用浮点 NA 的内部结构来做到这一点。这允许这些值在常规 R 操作中表现得与 NA 相同,同时仍保留标签的值。
用于创建带标签 NA
s 的 R 界面有点笨拙,因为通常它们会由 haven 为您创建。但是您可以使用 tagged_na():
创建自己的
重要:
请注意,这些标记的 NA 的行为与常规 NA 相同,即使在打印时也是如此。要查看他们的标签,请使用 print_tagged_na():
因此:
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=tagged_na("5"), refused= tagged_na("6")))
v3<-data.frame(v1 = v1, v2 = v2)
v3
lapply(v3, val_labels)
> v3
x x.1
1 1 1
2 2 2
3 2 2
4 2 2
5 5 5
6 6 6
> lapply(v3, val_labels)
$x
agree disagree dk refused
1 2 5 6
$x.1
agree disagree dk refused
1 2 NA NA
注意事项:
SPSS 的用户定义值与 SAS 和 Stata 的工作方式不同。每列可以有最多三个被视为缺失的不同值,或一个范围。 Haven 提供 labelled_spss()
作为 labelled() 的子类来模拟这些额外的用户定义缺失。
希望以上内容对您有所帮助
保重
T.
参考文献:
- https://cran.r-project.org/web/packages/haven/haven.pdf
- https://cran.r-project.org/web/packages/haven/vignettes/semantics.html
- https://www.spss-tutorials.com/spss-missing-values-tutorial/
使用 Public 数据的附录示例...
使用 SPPS 数据文件的 SPSS 缺失值示例 {hospital.sav}
首先,让我们确保我们强调
- 系统缺失值 - 是数据中完全不存在的值
- 用户缺失值是数据中存在但必须从计算中排除的值。
SPSS 数据视图...
让我们回顾一下图像和数据...变量视图中显示的 SPSS 数据显示每一行都有一个 标签 [第 5 列],我们注意到第 10 行到第 10 行14 个具有归因于它们的特定值 [1..6] [第 6 列] 具有名称属性并且没有值被指定为 Missing [第 7 列].
现在让我们看看SPSS数据视图:
这里我们可以注意到缺少数据...(请参阅突出显示的“.”)。关键是我们有缺失数据,但是目前没有"Missing User Values"
现在让我们转向R,并将数据加载到R
hospital_url <- "https://www.spss-tutorials.com/downloads/hospital.sav"
hospital <- read_sav(hospital_url,
user_na = FALSE)
head(hospital,5)
# We're interested in columns 10 through 14...
head(hospital[10:14],5)
结果
> hospital_url <- "https://www.spss-tutorials.com/downloads/hospital.sav"
> hospital <- read_sav(hospital_url,
+ user_na = FALSE)
> head(hospital,5)
# A tibble: 5 × 14
visit_id patient_id first_name surname_prefix last_name gender entry_date entry_time
<dbl> <dbl> <chr> <chr> <chr> <dbl+lbl> <date> <time>
1 32943 23176 JEFFREY DIJKSTRA 1 2013-01-08 16:56:10
2 32944 20754 MARK VAN DER BERG 1 2013-02-01 14:24:45
3 32945 25419 WILLEM VERMEULEN 1 2013-02-02 10:01:43
4 32946 21139 LINDA JANSSEN 0 2013-02-10 10:24:39
5 32947 25419 WILLEM VERMEULEN 1 2013-02-10 18:05:59
# ... with 6 more variables: exit_moment <dttm>, doctor_rating <dbl+lbl>, nurse_rating <dbl+lbl>,
# room_rating <dbl+lbl>, food_rating <dbl+lbl>, facilities_rating <dbl+lbl>
第 10 列到第 14 列包含值
1="Very Dissatisfied"
2="Dissatisfied"
3="Neutral"
4="Satisfied"
5="Very Satisfied"
6="Not applicable or don't want to answer"
因此:
> head(hospital[10:14],5)
# A tibble: 5 × 5
doctor_rating nurse_rating room_rating food_rating facilities_rating
<dbl+lbl> <dbl+lbl> <dbl+lbl> <dbl+lbl> <dbl+lbl>
1 5 5 4 2 3
2 4 5 4 3 3
3 5 6 4 5 4
4 4 5 5 4 4
5 5 5 6 6 6
SPSS 值标签
> lapply(hospital[10], val_labels)
$doctor_rating
Very dissatisfied Dissatisfied
1 2
Neutral Satisfied
3 4
Very satisfied Not applicable or don't want to answer
5 6
好的,请注意,上面我们可以确认我们已经导入了值标签。
从调查数据中删除不适用的数据
我们现在的目标是删除 "Not applicable or don't want to answer" 数据条目,方法是将它们设置为 "User NA values" 即SPSS 缺失值.
解决方案 - 第 1 步 - 单列
我们希望跨数据中的多个列设置缺失值属性...让我们首先对一列执行此操作...
注意我们使用 add_value_labels
而不是 set_value_labels
因为我们希望附加一个新标签,而不是完全覆盖现有标签...
d <- hospital
mean(d$doctor_rating, na.rm = TRUE)
d <- hospital %>%
add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
= tagged_na("6") )) %>%
set_na_values(doctor_rating = 5)
val_labels(d$doctor_rating)
mean(d$doctor_rating, na.rm = TRUE)
> d <- hospital
> mean(d$doctor_rating, na.rm = TRUE)
[1] 4.322368
> d <- hospital %>%
+ add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
+ = tagged_na("6") )) %>%
+ set_na_values(doctor_rating = 6)
> val_labels(d$doctor_rating)
Very dissatisfied Dissatisfied
1 2
Neutral Satisfied
3 4
Very satisfied Not applicable or don't want to answer
5 6
Not applicable or don't want to answer
NA
> mean(d$doctor_rating, na.rm = TRUE)
[1] 4.097015
解决方案 - 第 2 步 - 现在应用于多列...
mean(hospital$nurse_rating)
mean(hospital$nurse_rating, na.rm = TRUE)
d <- hospital %>%
add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
= tagged_na("6") )) %>%
set_na_values(doctor_rating = 6) %>%
add_value_labels( nurse_rating = c( "Not applicable or don't want to answer"
= tagged_na("6") )) %>%
set_na_values(nurse_rating = 6)
mean(d$nurse_rating, na.rm = TRUE)
结果
注意 nurse_rating 包含 "NaN" 值 和 NA 标记值。
第一个 mean() 调用失败,第二个调用成功,但在过滤器 "Not Applicable..." 被删除后包括 "Not Applicable..."...
> mean(hospital$nurse_rating)
[1] NaN
> mean(hospital$nurse_rating, na.rm = TRUE)
[1] 4.471429
> d <- hospital %>%
+ add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
+ = tagged_na("6") )) %>%
+ set_na_values(doctor_rating = 6) %>%
+ add_value_labels( nurse_rating = c( "Not applicable or don't want to answer"
+ = tagged_na("6") )) %>%
+ set_na_values(nurse_rating = 6)
> mean(d$nurse_rating, na.rm = TRUE)
[1] 4.341085
将标记的 NA 转换为 R NA
这里我们采用上面标记的 NA 并转换为 R NA 值。
d <- d %>% remove_labels(user_na_to_na = TRUE)
定义 SPSS 样式的用户定义缺失值
主要功能
labelled
包中用于处理 SPSS 样式用户定义缺失值的两个主要函数是 na_values
和 na_range
。
library(labelled)
v1 <-c(1,2,2,2,5,6)
val_labels(v1) <- c(agree=1, disagree=2, dk=5, refused=6)
na_values(v1) <- 5:6
v1
<Labelled SPSS double>
[1] 1 2 2 2 5 6
Missing values: 5, 6
Labels:
value label
1 agree
2 disagree
5 dk
6 refused
set_* 函数
labelled
中的 set_*
函数旨在与 magrittr
/ dplyr
一起使用。
library(dplyr)
d <- tibble(v1 = c(1, 2, 2, 2, 5, 6), v2 = c(1:3, 1:3))
d <- d %>%
set_value_labels(v1 = c(agree=1, disagree=2, dk=5, refused=6)) %>%
set_na_values(v1 = 5:6)
d$v1
<Labelled SPSS double>
[1] 1 2 2 2 5 6
Missing values: 5, 6
Labels:
value label
1 agree
2 disagree
5 dk
6 refused
什么是用户定义的缺失值?
用户定义的缺失值只是元信息。它不会更改向量中的值。这只是告诉用户这些值 could/should 在某些上下文中被视为缺失值的一种方式。这意味着如果您从向量中计算某些东西(例如平均值),这些值仍将被考虑在内。
mean(v1)
[1] 3
您可以使用 user_na_to_na
.
轻松地将用户定义的缺失值转换为正确的 NA
mean(user_na_to_na(v1), na.rm = TRUE)
[1] 1.75
很少有函数会考虑这些元信息。例如,参见 questionr
包中的 freq
函数。
library(questionr)
freq(v1)
n % val%
[1] agree 1 16.7 25
[2] disagree 3 50.0 75
[5] dk 1 16.7 NA
[6] refused 1 16.7 NA
NA 0 0.0 NA
标记的 NA 有什么区别?
haven
引入的标记 NA 的目的是重现 Stata 管理缺失值的方式。 R 在内部将所有标记的 NA 视为 NA
。
set_na_values
的第一个参数是数据框,而不是 vector/column,这就是为什么您的 lapply
命令不起作用的原因。您可以为数据框中任意数量的列构建 set_na_values
的参数列表,然后使用 do.call
调用它,如下所示...
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
na_values(v3)
args <- c(list(.data = v3), setNames(lapply(names(v3), function(x) c(5,6)), names(v3)))
v3 <- do.call(set_na_values, args)
na_values(v3)
更新: 您还可以在 lapply
语句中使用 na_values
函数的赋值形式,因为它接受向量作为第一个参数而不是像 set_na_values
...
这样的数据框
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
na_values(v3)
v3[] <- lapply(v3, function(x) `na_values<-`(x, c(5,6)))
na_values(v3)
甚至在 lapply
命令中使用 na_values
的普通版本,只需确保 return 'fixed' 向量...
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
na_values(v3)
v3[] <- lapply(v3, function(x) { na_values(x) <- c(5,6); x } )
na_values(v3)
而且这个想法也可以在 dplyr
链中使用,既可以应用于所有变量,也可以应用于使用 dplyr
的选择工具选择的任何列...
library(haven)
library(labelled)
library(dplyr)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
na_values(v3)
v4 <- v3 %>% mutate_all(funs(`na_values<-`(., c(5,6))))
na_values(v4)
v5 <- v3 %>% mutate_each(funs(`na_values<-`(., c(5,6))), x)
na_values(v5)
您可以使用一个非常简单的解决方案来使用 base
R:
v3[v3 == 5 ] <- NA
v3[v3 == 6 ] <- NA
但如果您正在寻找一个真正快速的解决方案,您可以使用 data.table
方法。
library(data.table)
setDT(v3)
for(j in seq_along(v3)) {
set(v3, i=which(v3[[j]] %in% c(5,6)), j=j, value=NA)
}
如何为数据框中的多个标记向量设置缺失值。我正在使用来自 spss 的调查数据集。我正在处理大约 20 个不同的变量,它们具有相同的缺失值。所以想找到一种方法来使用 lapply() 来完成这项工作,但我做不到。
我实际上可以通过 as.numeric() 和 recode() 使用 base R 来做到这一点,但我对 haven 和标记的 class 的可能性很感兴趣,所以我想在 Hadley 的 tidyverse
中找到一种方法来完成这一切感兴趣的变量大致如下所示。如果这是一个基本问题,我很抱歉,但我发现与 haven 和标签包相关的帮助文档非常无用。
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
lapply(v3, function(x) set_na_values(x, c(5,6)))
不太确定这是否是您要查找的内容:
v1 <- labelled(c(1, 2, 2, 2, 5, 6), c(agree = 1, disagree = 2, dk = 5, refused = 6))
v2 <- labelled(c(1, 2, 2, 2, 5, 6), c(agree = 1, disagree = 2, dk = 5, refused = 6))
v3 <- data_frame(v1 = v1, v2 = v2)
lapply(names(v3), FUN = function(x) {
na_values(v3[[x]]) <<- 5:6
})
lapply(v3, na_values)
返回最后一行
$v1
[1] 5 6
$v2
[1] 5 6
验证缺失值:
is.na(v3$v1)
[1] FALSE FALSE FALSE FALSE TRUE TRUE
这是正确的吗?
#Using replace to substitute 5 and 6 in v3 with NA
data.frame(lapply(v3, function(a) replace(x = a, list = a %in% c(5,6), values = NA)))
# x x.1
#1 1 1
#2 2 2
#3 2 2
#4 2 2
#5 NA NA
#6 NA NA
我知道 labelled_spss 允许您指定 na_range
甚至 na_values
#DATA
v11 = labelled_spss(x = c(1,2,2,2,5,6),
labels = c(agree=1, disagree=2, dk=5, refused=6),
na_range = 5:6)
#Check if v11 has NA values
is.na(v11)
#[1] FALSE FALSE FALSE FALSE TRUE TRUE
v22 = labelled_spss(x = c(1,2,2,2,5,6),
labels = c(agree=1, disagree=2, dk=5, refused=6),
na_range = 5:6)
#Put v11 and v22 in a list
v33 = list(v11, v22)
#Use replace like above
data.frame(lapply(X = v33, FUN = function(a) replace(x = a, list = is.na(a), values = NA)))
# x x.1
#1 1 1
#2 2 2
#3 2 2
#4 2 2
#5 NA NA
#6 NA NA
好的,我想我现在明白你想做什么了...
即在不删除基础导入数据的情况下将标签和值标记为 NA...
请参阅附录以获取更详细的示例,该示例使用 public 数据文件来显示利用 dplyr
更新多个列、标签的示例。 ..
建议的解决方案
df <- data_frame(s1 = c(1,2,2,2,5,6), s2 = c(1,2,2,2,5,6)) %>%
set_value_labels(s1 = c(agree=1, disagree=2, dk=5, refused=6),
s2 = c(agree=1, disagree=2, dk = tagged_na("5"), refused = tagged_na("6"))) %>%
set_na_values(s2 = c(5,6))
val_labels(df)
is.na(df$s1)
is.na(df$s2)
df
求解结果:
> library(haven)
> library(labelled)
> library(dplyr)
> df <- data_frame(s1 = c(1,2,2,2,5,6), s2 = c(1,2,2,2,5,6)) %>%
+ set_value_labels(s1 = c(agree=1, disagree=2, dk=5, refused=6),
+ s2 = c(agree=1, disagree=2, dk = tagged_na("5"), refused = tagged_na("6"))) %>%
+ set_na_values(s2 = c(5,6))
> val_labels(df)
$s1
agree disagree dk refused
1 2 5 6
$s2
agree disagree dk refused
1 2 NA NA
> is.na(df$s1)
[1] FALSE FALSE FALSE FALSE FALSE FALSE
> is.na(df$s2)
[1] FALSE FALSE FALSE FALSE TRUE TRUE
> df
# A tibble: 6 × 2
s1 s2
<dbl+lbl> <dbl+lbl>
1 1 1
2 2 2
3 2 2
4 2 2
5 5 5
6 6 6
现在我们可以操作数据了
mean(df$s1, na.rm = TRUE)
mean(df$s2, na.rm = TRUE)
> mean(df$s1, na.rm = TRUE)
[1] 3
> mean(df$s2, na.rm = TRUE)
[1] 1.75
使用Labeled package去除标签并替换为R NA
如果您希望去除标签并替换为 R NA 值,您可以使用 remove_labels(x, user_na_to_na = TRUE)
示例:
df <- remove_labels(df, user_na_to_na = TRUE)
df
结果:
> df <- remove_labels(df, user_na_to_na = TRUE)
> df
# A tibble: 6 × 2
s1 s2
<dbl> <dbl>
1 1 1
2 2 2
3 2 2
4 2 2
5 5 NA
6 6 NA
--
SPSS 格式说明/概述:
IBM SPSS(应用程序)可以以多种格式和非矩形配置导入和导出数据;但是,数据集总是被转换为 SPSS 矩形数据文件,称为系统文件(使用扩展名 *.sav)。变量格式、缺失值以及变量和值标签等元数据(有关数据的信息)与数据集一起存储。
价值标签
Base R 有一种数据类型可以有效地维护整数和字符标签之间的映射:因子。然而,这并不是因子的主要用途:它们被设计为自动为线性模型生成有用的对比。因素在重要方面与其他工具提供的标记值不同:
SPSS 和 SAS 可以标记数值和字符值,而不仅仅是整数值。
缺失值
这三个工具(SPSS、SAS、Stata)都提供了一个全局的“系统缺失值”,显示为.
。这大致等同于 R 的 NA
,尽管 Stata 和 SAS 都不会在数值比较中传播缺失值:SAS 将缺失值视为可能的最小数字(即 -inf),而 Stata 将其视为可能的最大数字(即inf).
每个工具还提供了一种记录多种缺失类型的机制:
- Stata 具有“扩展的”缺失值,.A 到 .Z。
- SAS 具有“特殊”缺失值,.A 到 .Z 加上 ._.
- SPSS 有每列“用户”缺失值。每列最多可以声明三个不同的值或一系列应视为缺失的值(加上一个不同的值)。
用户定义的缺失值
SPSS 的用户定义值与 SAS 和 Stata 的工作方式不同。每列可以有最多三个被视为缺失的不同值或一个范围。 Haven
提供 labelled_spss()
作为 labelled()
的子类来模拟这些额外的用户定义缺失。
x1 <- labelled_spss(c(1:10, 99), c(Missing = 99), na_value = 99)
x2 <- labelled_spss(c(1:10, 99), c(Missing = 99), na_range = c(90, Inf))
x1
#> <Labelled SPSS double>
#> [1] 1 2 3 4 5 6 7 8 9 10 99
#> Missing values: 99
#>
#> Labels:
#> value label
#> 99 Missing
x2
#> <Labelled SPSS double>
#> [1] 1 2 3 4 5 6 7 8 9 10 99
#> Missing range: [90, Inf]
#>
#> Labels:
#> value label
#> 99 Missing
标记缺失值
为了支持 Stata 的扩展和 SAS 的特殊缺失值,haven 实现了标记的 NA。它通过利用浮点 NA 的内部结构来做到这一点。这允许这些值在常规 R 操作中表现得与 NA 相同,同时仍保留标签的值。
用于创建带标签 NA
s 的 R 界面有点笨拙,因为通常它们会由 haven 为您创建。但是您可以使用 tagged_na():
重要:
请注意,这些标记的 NA 的行为与常规 NA 相同,即使在打印时也是如此。要查看他们的标签,请使用 print_tagged_na():
因此:
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=tagged_na("5"), refused= tagged_na("6")))
v3<-data.frame(v1 = v1, v2 = v2)
v3
lapply(v3, val_labels)
> v3
x x.1
1 1 1
2 2 2
3 2 2
4 2 2
5 5 5
6 6 6
> lapply(v3, val_labels)
$x
agree disagree dk refused
1 2 5 6
$x.1
agree disagree dk refused
1 2 NA NA
注意事项:
SPSS 的用户定义值与 SAS 和 Stata 的工作方式不同。每列可以有最多三个被视为缺失的不同值,或一个范围。 Haven 提供 labelled_spss()
作为 labelled() 的子类来模拟这些额外的用户定义缺失。
希望以上内容对您有所帮助
保重 T.
参考文献:
- https://cran.r-project.org/web/packages/haven/haven.pdf
- https://cran.r-project.org/web/packages/haven/vignettes/semantics.html
- https://www.spss-tutorials.com/spss-missing-values-tutorial/
使用 Public 数据的附录示例...
使用 SPPS 数据文件的 SPSS 缺失值示例 {hospital.sav}
首先,让我们确保我们强调
- 系统缺失值 - 是数据中完全不存在的值
- 用户缺失值是数据中存在但必须从计算中排除的值。
SPSS 数据视图...
让我们回顾一下图像和数据...变量视图中显示的 SPSS 数据显示每一行都有一个 标签 [第 5 列],我们注意到第 10 行到第 10 行14 个具有归因于它们的特定值 [1..6] [第 6 列] 具有名称属性并且没有值被指定为 Missing [第 7 列].
现在让我们看看SPSS数据视图:
这里我们可以注意到缺少数据...(请参阅突出显示的“.”)。关键是我们有缺失数据,但是目前没有"Missing User Values"
现在让我们转向R,并将数据加载到R
hospital_url <- "https://www.spss-tutorials.com/downloads/hospital.sav"
hospital <- read_sav(hospital_url,
user_na = FALSE)
head(hospital,5)
# We're interested in columns 10 through 14...
head(hospital[10:14],5)
结果
> hospital_url <- "https://www.spss-tutorials.com/downloads/hospital.sav"
> hospital <- read_sav(hospital_url,
+ user_na = FALSE)
> head(hospital,5)
# A tibble: 5 × 14
visit_id patient_id first_name surname_prefix last_name gender entry_date entry_time
<dbl> <dbl> <chr> <chr> <chr> <dbl+lbl> <date> <time>
1 32943 23176 JEFFREY DIJKSTRA 1 2013-01-08 16:56:10
2 32944 20754 MARK VAN DER BERG 1 2013-02-01 14:24:45
3 32945 25419 WILLEM VERMEULEN 1 2013-02-02 10:01:43
4 32946 21139 LINDA JANSSEN 0 2013-02-10 10:24:39
5 32947 25419 WILLEM VERMEULEN 1 2013-02-10 18:05:59
# ... with 6 more variables: exit_moment <dttm>, doctor_rating <dbl+lbl>, nurse_rating <dbl+lbl>,
# room_rating <dbl+lbl>, food_rating <dbl+lbl>, facilities_rating <dbl+lbl>
第 10 列到第 14 列包含值
1="Very Dissatisfied"
2="Dissatisfied"
3="Neutral"
4="Satisfied"
5="Very Satisfied"
6="Not applicable or don't want to answer"
因此:
> head(hospital[10:14],5)
# A tibble: 5 × 5
doctor_rating nurse_rating room_rating food_rating facilities_rating
<dbl+lbl> <dbl+lbl> <dbl+lbl> <dbl+lbl> <dbl+lbl>
1 5 5 4 2 3
2 4 5 4 3 3
3 5 6 4 5 4
4 4 5 5 4 4
5 5 5 6 6 6
SPSS 值标签
> lapply(hospital[10], val_labels)
$doctor_rating
Very dissatisfied Dissatisfied
1 2
Neutral Satisfied
3 4
Very satisfied Not applicable or don't want to answer
5 6
好的,请注意,上面我们可以确认我们已经导入了值标签。
从调查数据中删除不适用的数据
我们现在的目标是删除 "Not applicable or don't want to answer" 数据条目,方法是将它们设置为 "User NA values" 即SPSS 缺失值.
解决方案 - 第 1 步 - 单列
我们希望跨数据中的多个列设置缺失值属性...让我们首先对一列执行此操作...
注意我们使用 add_value_labels
而不是 set_value_labels
因为我们希望附加一个新标签,而不是完全覆盖现有标签...
d <- hospital
mean(d$doctor_rating, na.rm = TRUE)
d <- hospital %>%
add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
= tagged_na("6") )) %>%
set_na_values(doctor_rating = 5)
val_labels(d$doctor_rating)
mean(d$doctor_rating, na.rm = TRUE)
> d <- hospital
> mean(d$doctor_rating, na.rm = TRUE)
[1] 4.322368
> d <- hospital %>%
+ add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
+ = tagged_na("6") )) %>%
+ set_na_values(doctor_rating = 6)
> val_labels(d$doctor_rating)
Very dissatisfied Dissatisfied
1 2
Neutral Satisfied
3 4
Very satisfied Not applicable or don't want to answer
5 6
Not applicable or don't want to answer
NA
> mean(d$doctor_rating, na.rm = TRUE)
[1] 4.097015
解决方案 - 第 2 步 - 现在应用于多列...
mean(hospital$nurse_rating)
mean(hospital$nurse_rating, na.rm = TRUE)
d <- hospital %>%
add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
= tagged_na("6") )) %>%
set_na_values(doctor_rating = 6) %>%
add_value_labels( nurse_rating = c( "Not applicable or don't want to answer"
= tagged_na("6") )) %>%
set_na_values(nurse_rating = 6)
mean(d$nurse_rating, na.rm = TRUE)
结果
注意 nurse_rating 包含 "NaN" 值 和 NA 标记值。 第一个 mean() 调用失败,第二个调用成功,但在过滤器 "Not Applicable..." 被删除后包括 "Not Applicable..."...
> mean(hospital$nurse_rating)
[1] NaN
> mean(hospital$nurse_rating, na.rm = TRUE)
[1] 4.471429
> d <- hospital %>%
+ add_value_labels( doctor_rating = c( "Not applicable or don't want to answer"
+ = tagged_na("6") )) %>%
+ set_na_values(doctor_rating = 6) %>%
+ add_value_labels( nurse_rating = c( "Not applicable or don't want to answer"
+ = tagged_na("6") )) %>%
+ set_na_values(nurse_rating = 6)
> mean(d$nurse_rating, na.rm = TRUE)
[1] 4.341085
将标记的 NA 转换为 R NA
这里我们采用上面标记的 NA 并转换为 R NA 值。
d <- d %>% remove_labels(user_na_to_na = TRUE)
定义 SPSS 样式的用户定义缺失值
主要功能
labelled
包中用于处理 SPSS 样式用户定义缺失值的两个主要函数是 na_values
和 na_range
。
library(labelled)
v1 <-c(1,2,2,2,5,6)
val_labels(v1) <- c(agree=1, disagree=2, dk=5, refused=6)
na_values(v1) <- 5:6
v1
<Labelled SPSS double>
[1] 1 2 2 2 5 6
Missing values: 5, 6
Labels:
value label
1 agree
2 disagree
5 dk
6 refused
set_* 函数
labelled
中的 set_*
函数旨在与 magrittr
/ dplyr
一起使用。
library(dplyr)
d <- tibble(v1 = c(1, 2, 2, 2, 5, 6), v2 = c(1:3, 1:3))
d <- d %>%
set_value_labels(v1 = c(agree=1, disagree=2, dk=5, refused=6)) %>%
set_na_values(v1 = 5:6)
d$v1
<Labelled SPSS double>
[1] 1 2 2 2 5 6
Missing values: 5, 6
Labels:
value label
1 agree
2 disagree
5 dk
6 refused
什么是用户定义的缺失值?
用户定义的缺失值只是元信息。它不会更改向量中的值。这只是告诉用户这些值 could/should 在某些上下文中被视为缺失值的一种方式。这意味着如果您从向量中计算某些东西(例如平均值),这些值仍将被考虑在内。
mean(v1)
[1] 3
您可以使用 user_na_to_na
.
NA
mean(user_na_to_na(v1), na.rm = TRUE)
[1] 1.75
很少有函数会考虑这些元信息。例如,参见 questionr
包中的 freq
函数。
library(questionr)
freq(v1)
n % val%
[1] agree 1 16.7 25
[2] disagree 3 50.0 75
[5] dk 1 16.7 NA
[6] refused 1 16.7 NA
NA 0 0.0 NA
标记的 NA 有什么区别?
haven
引入的标记 NA 的目的是重现 Stata 管理缺失值的方式。 R 在内部将所有标记的 NA 视为 NA
。
set_na_values
的第一个参数是数据框,而不是 vector/column,这就是为什么您的 lapply
命令不起作用的原因。您可以为数据框中任意数量的列构建 set_na_values
的参数列表,然后使用 do.call
调用它,如下所示...
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
na_values(v3)
args <- c(list(.data = v3), setNames(lapply(names(v3), function(x) c(5,6)), names(v3)))
v3 <- do.call(set_na_values, args)
na_values(v3)
更新: 您还可以在 lapply
语句中使用 na_values
函数的赋值形式,因为它接受向量作为第一个参数而不是像 set_na_values
...
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
na_values(v3)
v3[] <- lapply(v3, function(x) `na_values<-`(x, c(5,6)))
na_values(v3)
甚至在 lapply
命令中使用 na_values
的普通版本,只需确保 return 'fixed' 向量...
library(haven)
library(labelled)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
na_values(v3)
v3[] <- lapply(v3, function(x) { na_values(x) <- c(5,6); x } )
na_values(v3)
而且这个想法也可以在 dplyr
链中使用,既可以应用于所有变量,也可以应用于使用 dplyr
的选择工具选择的任何列...
library(haven)
library(labelled)
library(dplyr)
v1<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v2<-labelled(c(1,2,2,2,5,6), c(agree=1, disagree=2, dk=5, refused=6))
v3<-data.frame(v1=v1, v2=v2)
lapply(v3, val_labels)
na_values(v3)
v4 <- v3 %>% mutate_all(funs(`na_values<-`(., c(5,6))))
na_values(v4)
v5 <- v3 %>% mutate_each(funs(`na_values<-`(., c(5,6))), x)
na_values(v5)
您可以使用一个非常简单的解决方案来使用 base
R:
v3[v3 == 5 ] <- NA
v3[v3 == 6 ] <- NA
但如果您正在寻找一个真正快速的解决方案,您可以使用 data.table
方法。
library(data.table)
setDT(v3)
for(j in seq_along(v3)) {
set(v3, i=which(v3[[j]] %in% c(5,6)), j=j, value=NA)
}