#r
Вопрос:
У меня возникла проблема, когда пропущенные значения преобразуются в фактическую символьную строку «NA» после использования case_when
— может ли кто-нибудь, пожалуйста, сообщить мне, где мой код неверен, и, возможно, предложить альтернативный метод, который не преобразует пропущенные значения в символьные строки?
Вот пример:
# make the tibble
df <- structure(list(animal = c("cat", "dog", "mouse", "rat",
"pidgeon", "fish"), value = c(-2.71, -2.63,
-2.66, -6.99, -2.11, -6.44), ID = c("2700",
NA, NA, "4821", "55117", NA)), row.names = c(NA, -6L
), class = c("tbl_df", "tbl", "data.frame"))
df
# A tibble: 6 x 3
animal value ID
<chr> <dbl> <chr>
1 cat -2.71 2700
2 dog -2.63 NA
3 mouse -2.66 NA
4 rat -6.99 4821
5 pidgeon -2.11 55117
6 fish -6.44 NA
# check that it has two NA values
sum(is.na(df$ID))
# [1] 3
# create a separate tibble to merge it with
new_vals <- structure(list(animal = c("dog", "pidgeon"), ID_new = c("123456", "25255")), row.names = c(NA, -2L), class = c("tbl_df",
"tbl", "data.frame"))
new_vals
# A tibble: 2 x 2
animal ID_new
<chr> <chr>
1 dog 123456
2 pidgeon 25255
Теперь я left_join
два тиббла и делаю case_when
заявление:
df_new <- left_join(
df,
new_vals,
by = "animal"
) %>%
mutate(
ID = case_when(
is.na(ID) ~ paste0(ID_new),
TRUE ~ paste0(ID)
)
)
> df_new
# A tibble: 6 x 4
animal value ID ID_new
<chr> <dbl> <chr> <chr>
1 cat -2.71 2700 NA
2 dog -2.63 123456 123456
3 mouse -2.66 NA NA
4 rat -6.99 4821 NA
5 pidgeon -2.11 55117 25255
6 fish -6.44 NA NA
sum(is.na(df_new$ID))
[1] 0
Хотя в df_new$ID явно есть значения NA, теперь они больше не считаются фактическими отсутствующими значениями. Где я ошибаюсь?
Ответ №1:
Причина paste0
в том, что в выражении есть ненужное
paste0(NA)
#[1] "NA"
Это задокументировано в ?paste
Обратите внимание, что функция paste() преобразует значение NA_character_, пропущенное значение символа, в «NA», что может показаться нежелательным, например, при вставке двух векторов символов или очень желательно,
Если намерение состоит в том, чтобы преобразовать в character
класс (хотя входные столбцы являются character
классами)
as.character(NA)
#[1] NA
возвращает правильный тип NA, т. е. NA_character_
. По сравнению с поведением paste
, stringr::str_c
возвращает правильный NA
по умолчанию
str_c(NA)
#[1] NA
is.na(str_c(NA))
#[1] TRUE
Поскольку это character
столбцы, и мы не выполняем никакого type
преобразования (при необходимости используйте as.character
вместо paste0
вставки как для объединения двух строк или столбцов строк вместе)
df_new <- left_join(
df,
new_vals,
by = "animal"
) %>%
mutate(
ID = case_when(
is.na(ID) ~ ID_new,
TRUE ~ ID
)
)
-тестирование на NA
sum(is.na(df_new$ID))
#[1] 2