我有一个奇怪的问题(也许我遗漏了什么?),当试图在if_else
内强制时区时(因为ifelse
似乎不能很好地处理POSIXct
)。它似乎仅在TRUE
时有效,而在FALSE
时才转换。为什么?如何解决?
library(lubridate)
library(dplyr)
some_date = ymd_hm("2020-06-01 17:45", tz = "America/New_York")
if_else(TRUE, force_tz(some_date, tz = "GMT"), force_tz(some_date, tz = "Singapore"))
[1] "2020-06-01 17:45:00 GMT"
if_else(FALSE, force_tz(some_date, tz = "GMT"), force_tz(some_date, tz = "Singapore"))
[1] "2020-06-01 09:45:00 GMT"
我期望与单独运行force_tz的结果相同:
# if TRUE
force_tz(some_date, tz = "GMT")
[1] "2020-06-01 17:45:00 GMT"
# if FALSE
force_tz(some_date, tz = "Singapore")
[1] "2020-06-01 17:45:00 +08"
谢谢!
罪魁祸首在方式 dplyr::if_else
进行调整。
首先,我对向量和TZ的原始评论仍然存在,并且仍然是这个问题的核心。记录:
当处理vector中的
POSIXt
时,TZ是整个向量的属性,而不是每个独立元素。这意味着(a)您必须接受向量中的所有时间戳都将具有相同的TZ;或(b)您需要调整流程以处理list
的时间戳,在这种情况下,每次都可以拥有自己的TZ。
如果您查看if_else
:
function (condition, true, false, missing = NULL)
{
if (!is.logical(condition)) {
bad_args("condition", "must be a logical vector, not {friendly_type_of(condition)}")
}
out <- true[rep(NA_integer_, length(condition))]
使用第一个(“ true”)向量的out
个变体预填充NA
向量。 (这是必要的,因为R实际上至少有6种NA
类型:逻辑(NA
),整数(NA_integer_
),实数/浮点数(NA_real_
),字符串(NA_character_
),日期([ C0])和时间(c.Date(NA)
);因此形成c.POSIXct(NA)
向量的[[how很重要。)但是,一旦预先填充NA
s的向量,就应意识到这是基于第一个向量,因此将其属性带到NA
向量中。
out
((请参阅中工作(使用其内部的Sys.time() # [1] "2020-06-01 09:02:06 PDT" now <- Sys.time() attr(now, "tzone") <- "GMT" dput(now) # structure(1591027335.41804, class = c("POSIXct", "POSIXt"), tzone = "GMT") dput(now[NA]) # structure(NA_real_, class = c("POSIXct", "POSIXt"), tzone = "GMT")
仍然如何)。这意味着输出向量(当对tzone=
个向量进行操作时)POSIXt
truewill always carry forward the TZ of the
if_else`。从这里开始,
argument to
在替换
if_else
,实际上是replace_with
)。替换<out[condition] <- false[condition]次的数值等效项是同化的,而不考虑其TZ。当然,false
向量的“世界绝对时间”被保留。唯一的解决方法是更改您的工作流程以处理false
为list
而不是向量。 POSIXt
仍在那儿工作。if_else