dplyr::if_else 更改日期时间 (POSIXct) 值
dplyr::if_else changes datetime (POSIXct) values
我正在处理一个包含大量时间戳的数据集。我尝试识别并设置为 NA 的一些无效时间戳。因为 if_else()
强制我的双臂具有相同的数据类型,所以我使用 as.POSIXct(NA)
来编码这些缺失值。
有趣的是,当我在 if_else()
.
中反转测试(并更改 true
和 false
参数时,结果不同
下面是一些代码来说明我的问题:
x <- tibble(
A = parse_datetime("2020-08-18 19:00"),
B = if_else(TRUE, A, as.POSIXct(NA)),
C = if_else(FALSE, as.POSIXct(NA), A)
)
> x
# A tibble: 1 x 3
A B C
<dttm> <dttm> <dttm>
1 2020-08-18 19:00:00 2020-08-18 19:00:00 2020-08-18 21:00:00
知道吗,为什么 C 晚了两个小时?
跟进:
基于下面的好答案,我认为一个更具可读性的解决方案或许应该使用 parse_datetime(NA_character_)
生成一个缺失的日期时间对象,并在代码中使用它而不是 as.POSIXct()
.
R> NA_datetime_ <- parse_datetime(NA_character_)
R> x <- tibble(
A = parse_datetime("2020-08-18 19:00"),
B = if_else(TRUE, A, NA_datetime_),
C = if_else(FALSE, NA_datetime_, A)
)
R> map(x, lubridate::tz)
$A
[1] "UTC"
$B
[1] "UTC"
$C
[1] "UTC"
这是一个时区问题:
lubridate::tz(x$A)
[1] "UTC"
lubridate::tz(x$B)
[1] "UTC"
lubridate::tz(x$C)
[1] ""
这是由于 if_else <- function (test, yes, no)
的工作方式:它使用 yes
参数的属性,对于 C 来说是 NA
.
首先,您需要知道 parse_datetime()
returns 具有 tzone
属性的 date-time object 默认为 UTC
。您可以使用 lubridate::tz(x$A)
和 attributes(x$A)
来检查它。
从if_else()
的文档中,它说true
和false
参数必须是同一类型。 所有其他属性取自true
。因此,部分 C
你的小标题:
C = if_else(FALSE, as.POSIXct(NA), A)
as.POSIXct(NA)
没有 tzone
属性,因此 A
的 tzone
被删除并重置为您所在地区的时区。实际上,C
是 而不是 两个小时后。 三列时间相等但时区不相等。要修复它,您可以将as.POSIXct(NA)
调整为拥有一个tzone
属性,即替换为
as.POSIXct(NA_character_, tz = "UTC")
注意: 您必须使用 NA_character_
而不是 NA
因为 tz
as.POSIXct()
中的参数仅适用于字符 objects.
最后,修改你的代码为
x <- tibble(
A = parse_datetime("2020-08-18 19:00"),
B = if_else(TRUE, A, as.POSIXct(NA_character_, tz = "UTC")),
C = if_else(FALSE, as.POSIXct(NA_character_, tz = "UTC"), A)
)
# # A tibble: 1 x 3
# A B C
# <dttm> <dttm> <dttm>
# 1 2020-08-18 19:00:00 2020-08-18 19:00:00 2020-08-18 19:00:00
记得检查他们的时区。
R > lubridate::tz(x$A)
[1] "UTC"
R > lubridate::tz(x$B)
[1] "UTC"
R > lubridate::tz(x$C)
[1] "UTC"
我正在处理一个包含大量时间戳的数据集。我尝试识别并设置为 NA 的一些无效时间戳。因为 if_else()
强制我的双臂具有相同的数据类型,所以我使用 as.POSIXct(NA)
来编码这些缺失值。
有趣的是,当我在 if_else()
.
true
和 false
参数时,结果不同
下面是一些代码来说明我的问题:
x <- tibble(
A = parse_datetime("2020-08-18 19:00"),
B = if_else(TRUE, A, as.POSIXct(NA)),
C = if_else(FALSE, as.POSIXct(NA), A)
)
> x
# A tibble: 1 x 3
A B C
<dttm> <dttm> <dttm>
1 2020-08-18 19:00:00 2020-08-18 19:00:00 2020-08-18 21:00:00
知道吗,为什么 C 晚了两个小时?
跟进:
基于下面的好答案,我认为一个更具可读性的解决方案或许应该使用 parse_datetime(NA_character_)
生成一个缺失的日期时间对象,并在代码中使用它而不是 as.POSIXct()
.
R> NA_datetime_ <- parse_datetime(NA_character_)
R> x <- tibble(
A = parse_datetime("2020-08-18 19:00"),
B = if_else(TRUE, A, NA_datetime_),
C = if_else(FALSE, NA_datetime_, A)
)
R> map(x, lubridate::tz)
$A
[1] "UTC"
$B
[1] "UTC"
$C
[1] "UTC"
这是一个时区问题:
lubridate::tz(x$A)
[1] "UTC"
lubridate::tz(x$B)
[1] "UTC"
lubridate::tz(x$C)
[1] ""
这是由于 if_else <- function (test, yes, no)
的工作方式:它使用 yes
参数的属性,对于 C 来说是 NA
.
首先,您需要知道 parse_datetime()
returns 具有 tzone
属性的 date-time object 默认为 UTC
。您可以使用 lubridate::tz(x$A)
和 attributes(x$A)
来检查它。
从if_else()
的文档中,它说true
和false
参数必须是同一类型。 所有其他属性取自true
。因此,部分 C
你的小标题:
C = if_else(FALSE, as.POSIXct(NA), A)
as.POSIXct(NA)
没有 tzone
属性,因此 A
的 tzone
被删除并重置为您所在地区的时区。实际上,C
是 而不是 两个小时后。 三列时间相等但时区不相等。要修复它,您可以将as.POSIXct(NA)
调整为拥有一个tzone
属性,即替换为
as.POSIXct(NA_character_, tz = "UTC")
注意: 您必须使用 NA_character_
而不是 NA
因为 tz
as.POSIXct()
中的参数仅适用于字符 objects.
最后,修改你的代码为
x <- tibble(
A = parse_datetime("2020-08-18 19:00"),
B = if_else(TRUE, A, as.POSIXct(NA_character_, tz = "UTC")),
C = if_else(FALSE, as.POSIXct(NA_character_, tz = "UTC"), A)
)
# # A tibble: 1 x 3
# A B C
# <dttm> <dttm> <dttm>
# 1 2020-08-18 19:00:00 2020-08-18 19:00:00 2020-08-18 19:00:00
记得检查他们的时区。
R > lubridate::tz(x$A)
[1] "UTC"
R > lubridate::tz(x$B)
[1] "UTC"
R > lubridate::tz(x$C)
[1] "UTC"