различные преобразования с lapply () - R - PullRequest
1 голос
/ 02 апреля 2019

У меня есть это df:

df <- structure(list(Created = structure(6:1, .Label = c("2018-12-27T08:53:32.794-0300", 
"2018-12-27T17:46:00.244-0300", "2019-01-17T17:16:08.222-0300", 
"2019-01-28T11:52:39.744-0300", "2019-01-28T11:55:34.723-0300", 
"2019-02-18T08:59:57.067-0300"), class = "factor"), Updated = structure(c(5L, 
3L, 2L, 1L, 4L, 6L), .Label = c("2019-03-04T17:41:30.895-0300", 
"2019-03-04T17:41:35.756-0300", "2019-03-08T15:37:32.071-0300", 
"2019-03-12T12:25:31.258-0300", "2019-03-12T16:20:48.210-0300", 
"2019-03-22T10:40:36.560-0300"), class = "factor"), Resolved = structure(c(5L, 
3L, 1L, 2L, 4L, 6L), .Label = c("2019-02-12T11:36:03.678-0300", 
"2019-02-27T09:09:58.990-0300", "2019-03-08T15:37:32.065-0300", 
"2019-03-12T12:25:31.251-0300", "2019-03-12T16:20:48.203-0300", 
"2019-03-22T10:40:36.553-0300"), class = "factor")), row.names = c(14L, 
28L, 29L, 30L, 37L, 38L), class = "data.frame")

> df
                        Created                      Updated                     Resolved
14 2019-02-18T08:59:57.067-0300 2019-03-12T16:20:48.210-0300 2019-03-12T16:20:48.203-0300
28 2019-01-28T11:55:34.723-0300 2019-03-08T15:37:32.071-0300 2019-03-08T15:37:32.065-0300
29 2019-01-28T11:52:39.744-0300 2019-03-04T17:41:35.756-0300 2019-02-12T11:36:03.678-0300
30 2019-01-17T17:16:08.222-0300 2019-03-04T17:41:30.895-0300 2019-02-27T09:09:58.990-0300
37 2018-12-27T17:46:00.244-0300 2019-03-12T12:25:31.258-0300 2019-03-12T12:25:31.251-0300
38 2018-12-27T08:53:32.794-0300 2019-03-22T10:40:36.560-0300 2019-03-22T10:40:36.553-0300

И мне нужно преобразовать их все в strptime(), поэтому для столбца Created:

Первый шаг: к символу:

df <- df %>% lapply(., as.character)

Второй шаг: сплит.

paste0(substr(df$Created,start=1,stop=10)," ", substr(df$Created,start=12,stop=19)," ",substr(df$Created,start=25,stop=29))

Третий шаг: до strptime()

df2 <- df %>%
  separate(Created, into = c("date", "time", "timezone"), sep = " ") %>%
  unite(col = Created, c("date", "time"), sep = " ") %>%
  mutate(Created = ymd_hms(Created)) %>%
  mutate(Created = if_else(timezone %in% "0300", Created + hours(1), Created)) %>%
  select(-timezone)

И все идеально:

> df2[1:5,c("Created")]
[1] "2019-02-18 11:59:57 UTC" "2019-01-28 14:55:34 UTC" "2019-01-28 14:52:39 UTC" "2019-01-17 20:16:08 UTC" "2018-12-27 20:46:00 UTC"

Тем не менее, я изо всех сил пытаюсь поместить это в lapply() функцию, так как это не просто 3 столбца, а почти 30. Любые предложения?

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Можно анализировать строки даты и времени с часовым поясом.Например: Разбор формата даты и времени ISO8601 в R

С небольшими изменениями вы можете сделать что-то вроде этого:

library(stringi)

df %>% 
  mutate_at(1:3, as.character) %>%
  mutate_at(1:3, function(x){
    x %>% stri_replace_first_regex("\\.\\d+", "") %>%
      strptime("%Y-%m-%dT%H:%M:%S%z", tz="UTC") %>%
      as.POSIXct()
  }) 

##               Created             Updated            Resolved
## 1 2019-02-18 11:59:57 2019-03-12 19:20:48 2019-03-12 19:20:48
## 2 2019-01-28 14:55:34 2019-03-08 18:37:32 2019-03-08 18:37:32
## 3 2019-01-28 14:52:39 2019-03-04 20:41:35 2019-02-12 14:36:03
## 4 2019-01-17 20:16:08 2019-03-04 20:41:30 2019-02-27 12:09:58
## 5 2018-12-27 20:46:00 2019-03-12 15:25:31 2019-03-12 15:25:31
## 6 2018-12-27 11:53:32 2019-03-22 13:40:36 2019-03-22 13:40:36

Изменяя первый аргументиз mutate_at, вы можете конвертировать все столбцы, которые хотите конвертировать.

Редактировать

Очевидно, что доли секунды также могут быть проанализированы.Модифицированный код (с небольшим количеством аннотаций):

string_conversion <- function(dt_string) {
  dt_string %>% 
    strptime("%Y-%m-%dT%H:%M:%S.%OS%z", tz="UTC") %>% # parse the string
    as.POSIXct() %>% # the end product is converted to POSIXct as POSIXlt is not supported.
    return()
}

df %>% 
  mutate_at(1:3, as.character) %>% # convert columns to characters
  mutate_at(1:3, string_conversion)
1 голос
/ 02 апреля 2019

ОП попросил использовать lapply, так что вот оно.

Первый, второй и третий шаги:

df[] <- lapply(df, function(column) {
    ## remove split seconds
    datetime <- stri_replace_first_regex(as.character(column), "\\.\\d+", "")
    ## identify the format of date, time, and zone in the string using strptime
    datetimestr <- strptime(datetime, "%Y-%m-%dT%H:%M:%S%z", tz="UTC")
    ## coerce to POSIXct and POSIXt classes 
    as.POSIXct(datetimestr)
})
...