为多个标记变量设置缺失值

spi*_*tor 15 r r-haven tidyverse

如何为数据框中的多个标记向量设置缺失值.我正在使用spss的调查数据集.我正在处理大约20个不同的变量,具有相同的缺失值.所以想找到一种方法来使用lapply()来完成这项工作,但我不能.

我实际上可以用基数R通过as.numeric()然后重新编码()来做到这一点,但我对避风港和标记类的可能性很感兴趣所以我想在Hadley的tidyverse中找到一种方法来做到这一切

大致相关的变量看起来像这样.如果这是一个基本问题,我很抱歉,但我发现与避风港相关联的帮助文档和标记的包只是非常无益.

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)))
Run Code Online (Sandbox Code Playgroud)

Tec*_*e01 10

好的,我想我现在明白你要做什么......

即标记标签,值为NA而不删除底层导入数据...

有关更详细的示例,请参阅附录,该示例使用公共数据文件来显示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
Run Code Online (Sandbox Code Playgroud)

解决方案结果

> 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
Run Code Online (Sandbox Code Playgroud)

现在我们可以操纵数据了

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
Run Code Online (Sandbox Code Playgroud)

使用Labeled包去除标签并用R NA替换

如果您想剥离标签并替换为可以使用的R NA值 remove_labels(x, user_na_to_na = TRUE)

例:

df <- remove_labels(df, user_na_to_na = TRUE)
df
Run Code Online (Sandbox Code Playgroud)

结果:

> 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
Run Code Online (Sandbox Code Playgroud)

-

SPSS格式的说明/概述:

IBM SPSS(应用程序)可以以多种格式和非矩形配置导入和导出数据; 但是,数据集始终转换为SPSS矩形数据文件,称为系统文件(使用扩展名*.sav).元数据(有关数据的信息)(如变量格式,缺失值以及变量和值标签)与数据集一起存储.

价值标签

Base R有一种数据类型可以有效地维护整数和字符标签之间的映射:因子.然而,这不是因素的主要用途:它们被设计为自动生成线性模型的有用对比.因素与其他工具在重要方面提供的标注值不同:

SPSS和SAS可以标记数字和字符值,而不仅仅是整数值.

缺少价值观

所有三个工具(SPSS,SAS,Strata)都提供全局"系统缺失值",显示为..这大致等同于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
Run Code Online (Sandbox Code Playgroud)

标记缺失值

为了支持Stata的扩展和SAS的特殊缺失值,避风港实现了标记的NA.它通过利用浮点NA的内部结构来实现这一点.这允许这些值在常规R操作中表现为与NA相同,同时仍然保留标记的值.

使用标记NAs 创建的R界面有点笨重,因为通常它们将由天堂为您创建.但您可以使用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)
Run Code Online (Sandbox Code Playgroud)
> 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 
Run Code Online (Sandbox Code Playgroud)

提醒:

SPSS的用户定义值与SAS和Stata的工作方式不同.每列可以包含最多三个被视为缺失的不同值或一个范围.Haven提供labelled_spss()了label()的子类来模拟这些额外的用户定义的缺失.

我希望以上有所帮助

小心T.

参考文献:

使用公共数据的附录示例...

SPSS缺失值使用SPPS数据文件的示例{ hospital.sav }

首先,我们要确保我们强调这一点

  • 系统缺失值 - 是数据中完全不存在的值
  • 用户缺失值是数据中存在的值,但必须从计算中排除.

SPSS数据视图......

让我们回顾一下图像和数据...变量视图中显示的SPSS数据显示每行都有一个Label [Column5],我们注意到第10行到第14行都有特定的值归属于它们[1..6] [列6]具有名称属性,并且没有任何值被指定为缺失 [第7列].

在此输入图像描述

现在让我们看一下SPSS数据视图:

在这里我们可以注意到缺少数据...(见高亮的".").关键是我们有丢失的数据,但目前没有"缺少用户价值"

在此输入图像描述

现在让我们转向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)
Run Code Online (Sandbox Code Playgroud)

结果

> 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>
Run Code Online (Sandbox Code Playgroud)

第10列到第14列包含值

1="Very Dissatisfied"
2="Dissatisfied"
3="Neutral"
4="Satisfied"
5="Very Satisfied"
6="Not applicable or don't want to answer"
Run Code Online (Sandbox Code Playgroud)

从而:

> 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

好的,请注意上面我们可以确认我们已经导入了Value Labels.

从调查数据中删除不适用的数据

我们的目标是通过将数据条目设置为"用户NA值"(即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)
Run Code Online (Sandbox Code Playgroud)
> 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
Run Code Online (Sandbox Code Playgroud)

解决方案 - 第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)
Run Code Online (Sandbox Code Playgroud)

结果

请注意,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
Run Code Online (Sandbox Code Playgroud)

将标记的NA转换为R NA

这里我们采用上面标记的NA并转换为R NA值.

d <- d %>% remove_labels(user_na_to_na = TRUE)
Run Code Online (Sandbox Code Playgroud)


CJ *_*man 1

第一个参数set_na_values是数据框,而不是向量/列,这就是您的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)
Run Code Online (Sandbox Code Playgroud)

更新:na_values您还可以在语句中使用函数的赋值形式lapply,因为它接受向量作为第一个参数,而不是像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)
Run Code Online (Sandbox Code Playgroud)

na_values或者甚至在命令中使用正常版本lapply,只需确保返回“固定”向量...

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)
Run Code Online (Sandbox Code Playgroud)

这个想法也可以在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)
Run Code Online (Sandbox Code Playgroud)