0

我有以下数据:

dat <- structure(list(value = structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
                                        label = "value: This is my label",
                                        labels = c(`No` = 0, `Yes` = 1),
                                        class = "haven_labelled"),
                      group = structure(c(1, 2, 1, 1, 2, 3, 3, 1, 3, 1, 3, 3, 1, 2, 3, 2, 1, 3, 3, 1),
                                        label = "my group",
                                        labels = c(first = 1, second = 2, third = 3),
                                        class = "haven_labelled")),
                 row.names = c(NA, -20L),
                 class = c("tbl_df", "tbl", "data.frame"),
                 label = "test.sav")

如您所见,数据使用了 tidyverse 的 Haven 包中的一个特殊类,即labelled列。

现在我想重新编码我的初始value变量,这样:

如果 group 等于 1,则 value 应该保持不变,否则应该丢失

我正在尝试以下操作,但出现错误:

dat_new <- dat %>%
  mutate(value = if_else(group != 1, NA, value))
# Error: `false` must be a logical vector, not a `haven_labelled` object

我了解到,来自 dplyr 的 if_else 要求 if_else 命令中的真假检查属于同一类,并且由于标记的类没有 NA 等效项(例如,类似于NA_real_双精度数),因此代码可能会失败,对?

那么,我怎样才能重新编码我的初始变量并保留标签

我知道我可以更改上面的代码并替换为if_elseR 的基本版本ifelse。但是,这会删除所有标签并将值列强制为数字列。

4

2 回答 2

1

haven_labelled您可以使用这个丑陋的代码在类中创建一个 NA 值:

haven::labelled(NA_real_, labels = attr(dat$value, "labels"))

我建议为此编写一个函数,例如

labelled_NA <- function(value) 
  haven::labelled(NA_real_, labels = attr(value, "labels"))

然后你的 mutate 的代码不是那么难看:

dat_new <- dat %>%
  mutate(value = if_else(group != labelled_NA(value), value)) 

然后你得到

> dat_new[1:5,]
# A tibble: 5 x 2
      value      group
  <dbl+lbl>  <dbl+lbl>
1   NA      1 [first] 
2   NA      2 [second]
3    0 [No] 1 [first] 
4    0 [No] 1 [first] 
5   NA      2 [second]
于 2020-04-28T23:06:47.453 回答
1

您可以尝试dplyr::case_whengroup == 1. 如果没有匹配的案例,NA则返回:

dat %>% mutate(value = case_when(group == 1 ~ value))
于 2020-04-29T03:47:08.900 回答