dplyr превращает даты в двойные при изменении данных - PullRequest
2 голосов
/ 16 января 2020

Я работаю с фреймом данных с датами и временем. Мне нужно установить для определенных столбцов даты значение NA, но когда я использую функцию mutate, столбцы даты превращаются в двойные столбцы!

Пример:

df
##   my_date_01    my_date_02
##   <date>        <date>    
## 1 2018-09-13    NA        
## 2 NA            2018-12-09
## 3 NA            2018-12-16
## 4 NA            2019-01-19
## 5 NA            2018-11-19
## 6 NA            2018-12-16
## 7 NA            2018-08-08
## 8 NA            2018-10-24
## 9 2019-03-26    NA        
##10 NA            2018-12-11

df %>% mutate(my_date_01 = ifelse(my_date_01 > lubridate::date("2019-01-01"), 
                                  NA, 
                                  my_date_01))
##   my_date_01    my_date_02
##   <dbl>         <date>    
## 1      17787    NA        
## 2         NA    2018-12-09
## 3         NA    2018-12-16
## 4         NA    2019-01-19
## 5         NA    2018-11-19
## 6         NA    2018-12-16
## 7         NA    2018-08-08
## 8         NA    2018-10-24
## 9         NA    NA        
##10         NA    2018-12-11

Две вещи здесь происходит:

  1. Нужные даты действительно заменяются на NA (это нормально), но
  2. Весь столбец преобразуется в двойной (это очень неправильно)

Чего мне не хватает?

1 Ответ

5 голосов
/ 16 января 2020

Мы можем обернуть as.Date(NA), чтобы получить тот же тип при выполнении сравнения

library(dplyr)
df %>% 
   mutate(my_date_01 = case_when(my_date_01 > lubridate::date("2019-01-01") 
                              ~ as.Date(NA), 
                              TRUE ~my_date_01))
# my_date_01 my_date_02
#1  2018-09-13       <NA>
#2        <NA> 2018-12-09
#3        <NA> 2018-12-16
#4        <NA> 2019-01-19
#5        <NA> 2018-11-19
#6        <NA> 2018-12-16
#7        <NA> 2018-08-08
#8        <NA> 2018-10-24
#9        <NA>       <NA>
#10       <NA> 2018-12-11

Исправление, приведенное выше, может все еще не работать с ifelse, поскольку в исходном коде ifelse

...
 ans <- test # assigned to logical vector test
    len <- length(ans)
    ypos <- which(test)
    npos <- which(!test)
    if (length(ypos) > 0L) 
        ans[ypos] <- rep(yes, length.out = len)[ypos]
    if (length(npos) > 0L) 
        ans[npos] <- rep(no, length.out = len)[npos]
    ans
}

Если вместо этого

ans <- as.Date(rep(NA, length(test)))

, он будет работать с кодом ниже, поскольку логический вектор приведен к цифре c при выполнении присваивания, которое не происходит с as.Date шаг выше

df %>% 
    mutate(my_date_01 = ifelsenew(my_date_01 > lubridate::date("2019-01-01"), 
                                   as.Date(NA), 
                                  my_date_01))

data

df <- structure(list(my_date_01 = structure(c(17787, NA, NA, NA, NA, 
NA, NA, NA, 17981, NA), class = "Date"), my_date_02 = structure(c(NA, 
17874, 17881, 17915, 17854, 17881, 17751, 17828, NA, 17876), class = "Date")), 
 row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")
...