Как использовать функцию lubridate as_datetime в сочетании с функциями dplyr mutate и case_when? - PullRequest
4 голосов
/ 26 марта 2019

Я пытаюсь манипулировать переменной dttm для настройки часовых поясов в зависимости от числового вектора идентификатора. Я могу манипулировать переменной в зависимости от идентификатора без проблем, используя вектор символов в качестве нового значения. Однако, когда я пытаюсь использовать функцию date_time() для создания нового значения, каждое значение получает результат первого элемента в case_when.

Вектор id числовой, и я попытался преобразовать класс в фактор и символ. Вопрос касается.

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#> 
#>     date

df1 <- tibble(
  id = c(1, 2, 3),
  date_time = rep(as_datetime("2018-01-01 12:34:56", tz = "Europe/Zurich"), 3)
) %>% 
  mutate(
    date_time2 = case_when(
      id == 1 ~ "one",
      id == 2 ~ "two",
      TRUE ~ "three"
    )
  )


df2 <- tibble(
  id = c(1, 2, 3),
  date_time = rep(as_datetime("2018-01-01 12:34:56", tz = "Europe/Zurich"), 3)
) %>% 
  mutate(
    date_time2 = case_when(
      id == 1 ~ as_datetime(date_time, tz = "America/New_York"),
      id == 2 ~ as_datetime(date_time, tz = "Asia/Kolkata"),
      TRUE ~ date_time
    )
  )

df3 <- tibble(
  id = c(1, 2, 3),
  date_time = rep(as_datetime("2018-01-01 12:34:56", tz = "Europe/Zurich"), 3)
) %>% 
  mutate(
    date_time2 = case_when(
      id == 1 ~ as_datetime(date_time, tz = "Asia/Kolkata"),
      id == 2 ~ as_datetime(date_time, tz = "America/New_York"),
      TRUE ~ date_time
    )
  )


df1 
#> # A tibble: 3 x 3
#>      id date_time           date_time2
#>   <dbl> <dttm>              <chr>     
#> 1     1 2018-01-01 12:34:56 one       
#> 2     2 2018-01-01 12:34:56 two       
#> 3     3 2018-01-01 12:34:56 three

df2
#> # A tibble: 3 x 3
#>      id date_time           date_time2         
#>   <dbl> <dttm>              <dttm>             
#> 1     1 2018-01-01 12:34:56 2018-01-01 06:34:56
#> 2     2 2018-01-01 12:34:56 2018-01-01 06:34:56
#> 3     3 2018-01-01 12:34:56 2018-01-01 06:34:56

df3
#> # A tibble: 3 x 3
#>      id date_time           date_time2         
#>   <dbl> <dttm>              <dttm>             
#> 1     1 2018-01-01 12:34:56 2018-01-01 17:04:56
#> 2     2 2018-01-01 12:34:56 2018-01-01 17:04:56
#> 3     3 2018-01-01 12:34:56 2018-01-01 17:04:56

Создано в 2019-03-26 пакетом представ. (v0.2.1)

df1 показывает, что я ожидаю.

В df2 я ожидаю, что date_time2 в id == 2 покажет «2018-01-01 17:04:56», а не «2018-01-01 06:34:56».

В df3 я ожидаю, что date_time2 в id == 3 покажет «2018-01-01 12:34:56», а не «2018-01-01 17:04:56».

Ответы [ 2 ]

1 голос
/ 26 марта 2019

Мы можем использовать force_tzs из пакета lubridate.Мы можем предоставить различные настройки часового пояса для аргумента tzones.В этом случае case_when не требуется, если вы знаете порядок часовых поясов.

library(dplyr)
library(lubridate)

df2 %>%
  mutate(date_time2 = force_tzs(date_time, tzones = c("America/New_York", "Asia/Kolkata", "UTC")))
# # A tibble: 3 x 3
#      id date_time           date_time2         
#   <dbl> <dttm>              <dttm>             
# 1     1 2018-01-01 12:34:56 2018-01-01 17:34:56
# 2     2 2018-01-01 12:34:56 2018-01-01 07:04:56
# 3     3 2018-01-01 12:34:56 2018-01-01 12:34:56

df3 %>%
  mutate(date_time2 = force_tzs(date_time, tzones = c("Asia/Kolkata", "America/New_York", "UTC")))
# # A tibble: 3 x 3
#      id date_time           date_time2         
#   <dbl> <dttm>              <dttm>             
# 1     1 2018-01-01 12:34:56 2018-01-01 07:04:56
# 2     2 2018-01-01 12:34:56 2018-01-01 17:34:56
# 3     3 2018-01-01 12:34:56 2018-01-01 12:34:56
1 голос
/ 26 марта 2019

это похоже на ошибку (вероятно, dpylr, поскольку раньше были проблемы с датами).

Вот возможная работа arround (не спрашивайте меня, почему она работает:))

tibble(
  id = c(1, 2, 3),
  date_time = rep(as_datetime("2018-01-01 12:34:56", tz = "Europe/Zurich"), 3)
) %>% 
  mutate(
    date_time2 = case_when(
      id == 1 ~ as_datetime(as.character(as_datetime(date_time, tz = "America/New_York"))),
      id == 2 ~ as_datetime(as.character(as_datetime(date_time, tz = "Asia/Kolkata"))),
      TRUE ~  as_datetime(as.character(date_time))

    )
  )

# A tibble: 3 x 3
     id date_time           date_time2         
  <dbl> <dttm>              <dttm>             
1     1 2018-01-01 12:34:56 2018-01-01 06:34:56
2     2 2018-01-01 12:34:56 2018-01-01 17:04:56
3     3 2018-01-01 12:34:56 2018-01-01 12:34:56
...