簡體   English   中英

R 與 function 發生變異,case_when 和數據屏蔽以解析時間戳

[英]R mutate across with function, case_when and data masking to parse timestamps

我正在嘗試使用 R mutatecase_when將一些時間戳(字符向量)解析為日期時間。

虛擬數據:

p_id = c(1,2,3,4,5,6)
ActualStartTime = c("2020-05-21 19:04:36 +01:00", "21/09/2020 14:14", "2020-08-18 10:11:08 +01:00", "12/10/2020 21:25", "09/11/2020 17:02","2020-05-16 11:50:58 +02:00")
ActualEndTime = c("2020-05-21 19:29:42 +01:00", "21/09/2020 14:19", "2020-08-18 10:14:26 +01:00", "12/10/2020 21:29", "09/11/2020 17:06", "2020-05-16 11:56:10 +02:00")
df <- data.frame(p_id,ActualStartTime, ActualEndTime)

df

  p_id            ActualStartTime              ActualEndTime
1    1 2020-05-21 19:04:36 +01:00 2020-05-21 19:29:42 +01:00
2    2           21/09/2020 14:14           21/09/2020 14:19
3    3 2020-08-18 10:11:08 +01:00 2020-08-18 10:14:26 +01:00
4    4           12/10/2020 21:25           12/10/2020 21:29
5    5           09/11/2020 17:02           09/11/2020 17:06
6    6 2020-05-16 11:50:58 +02:00 2020-05-16 11:56:10 +02:00

時間戳有兩種不同的格式,因此我創建了一個 function,但沒有對其進行矢量化以對其進行測試。 如果長度 == 26 則它使用一種格式進行解析,如果長度為其他任何格式,則它解析為另一種格式。

parse_mydate_novec <- function(time_var) {
  if (nchar(time_var) == 26) { 
    parse_date_time(time_var, orders = "%Y-%m-%d %H:%M:%S %z", tz = "UTC")
  } else {
    parse_date_time(time_var, orders = "%d/%m/%Y %H:%M", tz = "UTC")
  }
}

parse_mydate_novec(df$ActualStartTime[1]) # this works, class is POSIXct
[1] "2020-05-21 18:04:36 UTC"

> parse_mydate_novec(df$ActualStartTime[2]) # this works, class is POSIXct
[1] "2020-09-21 14:14:00 UTC"

到目前為止,一切都很好。 然后,我嘗試使用數據屏蔽指南https://dplyr.tidyverse.org/reference/dplyr_data_masking.html對 function 進行矢量化,這樣我就可以將它與 mutate 一起使用,並使用 case_when 而不是 if else:

parse_mydate <- function(time_var) {
 case_when (
   nchar({{time_var}}) == 26 ~ parse_date_time({{time_var}}, orders = "%Y-%m-%d %H:%M:%S %z", tz = "UTC"),
   nchar({{time_var}}) == 16 ~ parse_date_time({{time_var}}, orders = "%d/%m/%Y %H:%M", tz = "UTC"),
   TRUE ~ {{time_var}})
} 

然后我使用 mutate 傳遞這個 function,首先在一列上對其進行測試,然后使用 mutate(across()):

df_test <- df %>%
  mutate(ActualStartTime = parse_mydate(ActualStartTime))

df_test <- df %>%
  mutate(across(c(ActualStartTime, ActualEndTime), ~parse_mydate(.x)))

但是我收到以下錯誤:

Error in `mutate_cols()`:
! Problem with `mutate()` column `ActualStartTime`.
ℹ `ActualStartTime = parse_um_date(ActualStartTime)`.
x must be a `POSIXct/POSIXt` object, not a character vector.
Caused by error in `glubort()`:
! must be a `POSIXct/POSIXt` object, not a character vector.

Warning messages:
1: Problem with `mutate()` column `ActualStartTime`.
ℹ `ActualStartTime = parse_um_date(ActualStartTime)`.
ℹ  3 failed to parse. 
2: Problem with `mutate()` column `ActualStartTime`.
ℹ `ActualStartTime = parse_um_date(ActualStartTime)`.
ℹ  3 failed to parse. 

這沒有意義,因為我編寫了 function 以傳入字符向量並返回日期時間 object。

所需的 output 是 dataframe,其中 ActualStartTime 和 ActualEndTime 中的所有對象均為 POSIXct 格式,即“2020-05-21 18:04:36 UTC”

我看過: R dplyr using across() efficiently with mutate() and case_when()R - How to pass parameters to function in "mutate across"? 以及其他幾個關於解析日期時間的問題。

不知道是我function的邏輯錯了,是用case_when,還是用mutate還是別的什么。 我一直在兜圈子幾個小時。 所有幫助表示贊賞。 感謝。

function lubridate::fast_strptime允許指定更多格式,這些格式將依次應用直到成功。

library(dplyr)
library(lubridate)

df %>%
  mutate(across(matches("Time"), ~fast_strptime(.x,
                                              format = c("%Y-%m-%d %H:%M:%S %z",
                                                         "%d/%m/%Y %H:%M"),
                                              tz = "UTC")))


##>   p_id     ActualStartTime       ActualEndTime
##> 1    1 2020-05-21 18:04:36 2020-05-21 18:29:42
##> 2    2 2020-09-21 14:14:00 2020-09-21 14:19:00
##> 3    3 2020-08-18 09:11:08 2020-08-18 09:14:26
##> 4    4 2020-10-12 21:25:00 2020-10-12 21:29:00
##> 5    5 2020-11-09 17:02:00 2020-11-09 17:06:00
##> 6    6 2020-05-16 09:50:58 2020-05-16 09:56:10

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM