从Posixct对象中提取日期和小时,使用strftime

3
我试着从日期时间列中用strftime提取日期和小时,但我不明白为什么返回的值比应该返回的值早1小时。例如,对于2013-01-01 00:00:00的日期时间,返回的值应该是2013-01-01 00,但我得到的是2012-12-31 23。我还尝试添加1小时,然后再提取,但在一长串日期上,这又扰乱了输出。请参考以下示例代码。
## creating the sequence of time steps for cleaned
start <- as.POSIXct('2013-01-01 00:00:00',tz='EST')
end <- as.POSIXct('2016-06-06 23:00:00',tz='EST')

timesteps = data.frame( seq.POSIXt(from = start, to =end , by = "5 min"))
colnames(timesteps) = "Time Index"

dateandhour = function (timeindex){
return(strftime(timeindex, format = "%Y-%m-%d %H"))
}

timesteps ['Date and Hour'] = sapply(timesteps$`Time Index`, dateandhour)

请告诉我这里我缺少了什么。非常感谢。

2个回答

2
这是因为你在as.POSIXct中指定了时区,但在strptime中没有指定。
timesteps[1,1]
[1] "2013-01-01 EST"

 strftime(timesteps[1,1], format = "%Y-%m-%d %H")
[1] "2012-12-31 21"
 strftime(timesteps[1,1], format = "%Y-%m-%d %H",tz='EST')
[1] "2013-01-01 00"`

dateandhour = function (timeindex){
  return(strftime(timeindex, format = "%Y-%m-%d %H",tz='EST'))
}

timesteps ['Date and Hour'] = sapply(timesteps$`Time Index`, dateandhour)

head(timesteps)
           Time Index Date and Hour
1 2013-01-01 00:00:00 2013-01-01 00
2 2013-01-01 00:05:00 2013-01-01 00
3 2013-01-01 00:10:00 2013-01-01 00
4 2013-01-01 00:15:00 2013-01-01 00
5 2013-01-01 00:20:00 2013-01-01 00
6 2013-01-01 00:25:00 2013-01-01 00

1
感谢您指出 as.POSIXct 的错误。您的回答真的很有帮助。 - Harshit Saxena

1

这里是一个两行的答案:

创建序列

df <- data.frame(TimeIndex = 
         seq(anytime("2013-01-01 00:00:00"), 
             anytime("2016-06-06 23:00:00"), by="5 min"))

这将创建361k个观测值:
R> dim(df)
[1] 360841      1
R> 

转换为日期和小时

由于R是向量化的,因此您可以在一次操作中完成此操作:

df$DateAndHour <- strftime(df$TimeIndex, "%Y-%m-%d %H")

并且我们可以检查:

R> head(df, 10)
             TimeIndex   DateAndHour
1  2013-01-01 00:00:00 2013-01-01 00
2  2013-01-01 00:05:00 2013-01-01 00
3  2013-01-01 00:10:00 2013-01-01 00
4  2013-01-01 00:15:00 2013-01-01 00
5  2013-01-01 00:20:00 2013-01-01 00
6  2013-01-01 00:25:00 2013-01-01 00
7  2013-01-01 00:30:00 2013-01-01 00
8  2013-01-01 00:35:00 2013-01-01 00
9  2013-01-01 00:40:00 2013-01-01 00
10 2013-01-01 00:45:00 2013-01-01 00
R> 

我使用anytime,因为我觉得它紧凑而方便——不需要格式。我们也可以使用as.POSIXct()strptime()
我还省略了tz参数,以便所有内容都在我的本地时区。您可以在每次调用anytime()strftime()时设置它,或设置TZ环境变量。 编辑: OP询问性能,这里是一个快速比较。我需要稍微修改一下解决方案:
df <- data.frame(TimeIndex = seq(anytime("2013-01-01 00:00:00"),
                                 anytime("2016-06-06 23:00:00"), by="5 min"))

dateandhour <- function (timeindex) {
    return(strftime(timeindex, format = "%Y-%m-%d %H"))
}

f1 <- function(df) { data.frame(TimeIndex=df, DateAndHour=sapply(df, dateandhour)) }
f2 <- function(df) { data.frame(TimeIndex=df, DateAndHour=strftime(df$TimeIndex, "%Y-%m-%d %H")) }

library(rbenchmark)

benchmark(f1(df), f2(df), replications=10)[,1:4]

使用这个,我得到了这个:
R> benchmark(f1(df), f2(df), replications=10)[,1:4]
    test replications elapsed relative
1 f1(df)           10   7.101     2.08
2 f2(df)           10   3.414     1.00
R> 

关于两倍的改进。

谢谢你的回答。我真的很喜欢你使用 anytime 函数来减少编程步骤,但对于非常大的数据集,哪种方法更有效呢? - Harshit Saxena
向量化的解决方案通常胜过sapply。请查看我的详细回答。 - Dirk Eddelbuettel
完美!谢谢。 - Harshit Saxena
所以我实际上写了两个答案,而你却懒得点赞。我认为我的答案显然比被接受的答案更好(包含所有逻辑,代码更短更快)。简而言之,在这里不是这样运作的,因为你提供了零激励。 - Dirk Eddelbuettel
你好!我在你第一次回答后就试图给你点赞,但是它给了我一个消息,说“感谢您的反馈。那些声望低于15的人投票会被记录下来,但不会改变公开显示的分数。” - Harshit Saxena
我的当前声望是13,因为我最近加入了Stack Overflow。一旦我达到声望15,我会确保给你的答案点赞。再次感谢你的回答。 - Harshit Saxena

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接