Как добавить к дате с ifelse - PullRequest
1 голос
/ 30 апреля 2020

У меня есть фрейм данных со столбцом для даты и текстовым столбцом с именем Rule. Если текст в столбце правил - «Rule_1», я хочу добавить 3 года к дате в этой строке, но если «Rule_2», то два года.

Date        Rule     NewDate
2010-01-01  Rule_1   2013-01-01
2012-01-01  Rule_2   2014-01-01
2015-01-01  No_Rule  2015-01-01

Мне кажется, проблема с добавлением года с использованием lubridate

 ifelse(df$Rule=="Rule1",df$Date %m+% years(3),df$Date)

Он преобразует добавленную дату в число, которое, я думаю, является числом дней от начала координат (? 1970). Однако, если я запускаю выражение df$Date %m+% years(3) без ifelse, то оно работает нормально. Что делать?

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

Поскольку вы уже используете один tidyverse пакет (lubridate), как насчет case_when из dplyr? Это векторизация if - и, в основном, позволяет вам избежать множества вложенных операторов ifelse, если у вас несколько условий.

library(dplyr)
df %>% 
  mutate(NewDate_Demo = case_when(Rule == "Rule_1" ~ Date %m+% years(3),
                          Rule == "Rule_2" ~ Date %m+% years(2),
                          TRUE ~ Date))
# A tibble: 3 x 4
  Date       Rule    NewDate    NewDate_Demo
  <date>     <chr>   <date>     <date>      
1 2010-01-01 Rule_1  2013-01-01 2013-01-01  
2 2012-01-01 Rule_2  2014-01-01 2014-01-01  
3 2015-01-01 No_Rule 2015-01-01 2015-01-01  

dplyr также предлагает if_else, который имеет то же самое общий синтаксис как base::ifelse, но не ломается с lubridate https://github.com/tidyverse/lubridate/issues/644

0 голосов
/ 30 апреля 2020

Базовая функция ifelse нестабильна по типу. Скорее используйте, если реализация dplyr if_else(). Это автоматически проверяет и сохраняет желаемый тип вывода. Из документации:

По сравнению с базовым ifelse () эта функция более строгая. Он проверяет, что true и false имеют одинаковый тип. Эта строгость делает тип вывода более предсказуемым и делает его несколько быстрее.

library(dplyr)
library(lubridate)

# never mix up tidyverse and data.table but damn, fread() is awesome :D 
df <- data.table::fread("
Date        Rule     NewDate
2010-01-01  Rule_1   2013-01-01
2012-01-01  Rule_2   2014-01-01
2015-01-01  No_Rule  2015-01-01") %>% 
  as_tibble() %>% 
  mutate_at(.vars = c(1, 3), as_date)

# more type stable ifelse
dplyr::if_else(df$Rule=="Rule_1", df$Date %m+% years(3), df$Date)

# desired output with nested if_else
# faster than case_when()
dplyr::if_else(df$Rule=="Rule_1", df$Date %m+% years(3), 
               if_else(df$Rule=="Rule_2", df$Date %m+% years(2), df$Date))

# piped dplyr way
df %>% 
  mutate(desired_date = if_else(Rule == "Rule_1",
                                true = Date %m+% years(3), 
                                false = if_else(Rule == "Rule_2", 
                                                true = Date %m+% years(2),
                                                false = Date)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...