как я могу изменить символ на тип даты и времени с помощью ifelse? - PullRequest
1 голос
/ 06 марта 2020

Предположим, я хочу преобразовать число, такое как "43843", в формат даты и времени (файл читается из Excel, поэтому некоторые файлы имеют правильный формат даты и времени; но другие показали символ, такой как "43875", который является днями с 1899-12-30); но некоторые уже в типе даты и времени; поэтому я использовал ifelse для оценки типа столбца, а затем применил функцию as.posixct. но похоже не работает. Я не знаю почему.

> tt <- as.POSIXct(c("2020-1-9","2020-2-1","2020-2-8"))
> dd1 <- tibble(tt,1:3)
> ts <- c("43843","43842","43844")
> dd2 <- tibble(tt=ts,1:3)
> dd1 %>% 
+     mutate(tt = ifelse(is.POSIXct(tt),tt,
+                        as.POSIXct(as.Date(as.numeric(tt), origin = "1899-12-30"))))
# A tibble: 3 x 2
          tt `1:3`
       <dbl> <int>
1 1578499200     1
2 1578499200     2
3 1578499200     3
> dd2 %>% 
+     mutate(tt = ifelse(is.POSIXct(tt),tt,
+                        as.POSIXct(as.Date(as.numeric(tt), origin = "1899-12-30"))))
# A tibble: 3 x 2
          tt `1:3`
       <dbl> <int>
1 1578873600     1
2 1578873600     2
3 1578873600     3

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

Я думаю, что это больше проблема if() else, чем проблема векторизации ifelse(). Помните о проблемах с часовым поясом, так как вы определяете время в часовом поясе вашей системы, а также вводите данные, которые не имеют смещения от GMT.

В любом случае ...

convfun <- function(x) {
  if(is.POSIXct(x)) {x} else {
    as.POSIXct(format(as.POSIXct(as.numeric(x)*86400, origin="1899-12-30", tz="UTC")))
  }
}

dd1 %>% mutate(tt = convfun(tt))
## A tibble: 3 x 2
#  tt                  `1:3`
#  <dttm>              <int>
#1 2020-01-09 00:00:00     1
#2 2020-02-01 00:00:00     2
#3 2020-02-08 00:00:00     3

dd2 %>% mutate(tt = convfun(tt))
## A tibble: 3 x 2
#  tt                  `1:3`
#  <dttm>              <int>
#1 2020-01-13 00:00:00     1
#2 2020-01-12 00:00:00     2
#3 2020-01-14 00:00:00     3

Проверка оба в одном часовом поясе:

(dd1 %>% mutate(tt = convfun(tt)))$tt
#[1] "2020-01-09 AEST" "2020-02-01 AEST" "2020-02-08 AEST"
(dd2 %>% mutate(tt = convfun(tt)))$tt
#[1] "2020-01-13 AEST" "2020-01-12 AEST" "2020-01-14 AEST"
1 голос
/ 06 марта 2020

Значения, которые уже имеют тип даты-времени, являются символами, поскольку столбец может содержать данные только одного типа, поэтому is.POSIXct не будет работать. Попробуйте следующее:

library(dplyr)

dd2 %>%
   mutate(tt1 = replace(as.POSIXct(tt, format = "%Y-%m-%d %T"), 
                         grepl('^[0-9]*$', tt), NA), 
          tt = as.POSIXct(as.Date(as.numeric(tt), origin = "1899-12-30")),
          final = coalesce(tt1, tt))

Сначала создается столбец (tt1) типа POSIXct, который содержит значения данных, которые имеют дату и время, и имеет NA для дат. Затем мы изменяем даты (которые являются числами) на формат POSIXct, а затем объединяем столбцы, используя coalesce.

...