为什么舍入 POSIXct 会改变匹配等效 POSIXct 的能力?

问题描述 投票:0回答:1

有人可以向我解释为什么以下 POSIXct 时间元素不“匹配”吗?

我最终试图将向量

time
中的日期时间值与向量
datetime
中的日期时间值进行匹配。我已经简化了示例,以便所有内容都是相同的日期,只有小时值不同。在这个例子中,我可以使用
match
来查找
time
中每个
datetime
的索引位置。但是,如果我需要将
time
中的日期时间四舍五入到最接近的小时,此处给出的
roundtime
突然匹配失败?但是
time==roundtime
?我在这里缺少什么?

datetime <- as.POSIXct("2020-01-01 15:00:00",tz="UTC") + (0:10) * 3600
time <- as.POSIXct(c("2020-01-01 15:00:00", "2020-01-01 16:00:00", "2020-01-01 21:00:00"),tz='UTC')
roundtime<-round(time,units="hours")

time %in% datetime # gives TRUES
time %in% roundtime # give FALSES?
time == roundtime # gives TRUES
match(time, datetime) # returns matches
match(time, roundtime) # No matches?
match(roundtime, datetime) # no matches?
r datetime posixct
1个回答
0
投票

这个答案扩展了我对OP原始问题的评论。

该问题似乎是由使用

round
:

引起的静默类更改引起的
class(time)
[1] "POSIXct" "POSIXt" 
class(datetime)
[1] "POSIXct" "POSIXt" 

但是

class(roundtime)
[1] "POSIXlt" "POSIXt"

执行类更改时不会发出警告或注释,并且被默认的 S3

print
方法隐藏:

print(datetime[1])
"2020-01-01 15:00:00 UTC"
print(time[1])
[1] "2020-01-01 15:00:00 UTC"
print(roundtime[1])
[1] "2020-01-01 15:00:00 UTC"

但是,当对象被

unclass
编辑时就很明显了:

print(unclass(datetime[1]))
[1] 1577890800
attr(,"tzone")
[1] "UTC"
print(unclass(time[1]))
[1] 1577890800
attr(,"tzone")
[1] "UTC"
print(unclass(roundtime[1]))
$sec
[1] 0

$min
[1] 0

$hour
[1] 15

$mday
[1] 1

$mon
[1] 0

$year
[1] 120

$wday
[1] 3

$yday
[1] 0

$isdst
[1] 0

attr(,"tzone")
[1] "UTC"

match
失败了,因为正如其在线文档中所明确的那样,“因子、原始向量和列表被转换为字符向量,内部分类对象通过 mtfrm 进行转换,然后 x 和 table 被强制为通用类型( R 排序中两种类型中较晚的一种,逻辑 < integer < numeric < complex < character) before matching. ... Exactly what matches what is to some extent a matter of definition".

这个问题可以通过使用

lubridate
来避免:

library(lubridate)
roundtime1 <- floor_date(datetime, "hour")
class(roundtime1)
[1] "POSIXct" "POSIXt" 
match(time, roundtime1)
[1] 1 2 7
match(roundtime1, datetime)
 [1]  1  2  3  4  5  6  7  8  9 10 11
> 

正如 @r2evans 所写,这是一个无声的、令人讨厌的陷阱,可能会导致难以识别和避免的意外行为。

© www.soinside.com 2019 - 2024. All rights reserved.