【问题标题】:lubridate converting midnight timestamp returns NA: how to fill missing timestamplubridate 转换午夜时间戳返回 NA:如何填充缺少的时间戳
【发布时间】:2017-09-02 15:14:24
【问题描述】:

我在 R 中有一个从 CSV 导入的数据框。 csv 中的“时间”格式为“%Y-%m-%d %H:%M:%S”,如下所示:

> head(btc_data)
                 time  btc_price
1 2017-08-27 22:50:00 4,389.6113
2 2017-08-27 22:51:00 4,389.0850
3 2017-08-27 22:52:00 4,388.8625
4 2017-08-27 22:53:00 4,389.7888
5 2017-08-27 22:56:00 4,389.9138
6 2017-08-27 22:57:00 4,390.1663

当我运行str(btc_data) 时,时间列作为一个因素回来了。因此,我使用 lubridate 包将其转换为日期时间,如下所示:

btc_data$time <- ymd_hms(as.character(btc_data$time)) 

问题是在午夜收集的数据(5 行)无法解析并返回这样的 NA 值(在原始数据中,这些行中缺少时间戳,因此2017-08-29 00:00:00 被简单地列为2017-08-29) -

724 2017-08-28 23:59:00  4,439.3313
725 NA                   4,439.6588
726 2017-08-29 00:01:00  4,440.3050

此外,第二个数据框的组织方式不同:

> str(eth_data)
'data.frame':   1081 obs. of  2 variables:
 $ time     : Factor w/ 1081 levels "8/28/17 16:19",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ eth_price: num  344 344 344 344 343 ...

当我尝试时:

> eth_data$time <- mdy_hms(as.character(eth_data$time))

我收到以下错误:

警告消息:所有格式都无法解析。未找到格式。

编辑:我已隔离导致问题的代码问题:

> btc_data[721:726,]
                   time  btc_price
721 2017-08-28 23:57:00 4,439.8163
722 2017-08-28 23:58:00 4,440.2363
723 2017-08-28 23:58:00 4,440.2363
724 2017-08-28 23:59:00 4,439.3313
725 2017-08-29          4,439.6588
726 2017-08-29 00:01:00 4,440.3050

因此,每次午夜钟声敲响时,都不会记录时间戳。 CSV 是通过数据流创建的并且不断增长,因此除非我能找到解决方法,否则这个问题每天都会继续出现。有什么建议吗?

【问题讨论】:

  • 请包括失败的行。
  • 请看我的编辑——我添加了失败的行,第二个 df 完全失败了。
  • 在 lubridate 有机会捣碎它之前,向我们展示 text。是 00:00:00 还是 24:00:00?
  • 手动为这些元素添加时间:with(df, ifelse(nchar(date) == 10, paste(date, "00:00:00"), date)),然后使用as.POSIXct进行转换
  • 在此之前就行btc_data$time &lt;- as.character(btc_data$time)。下面的答案也显示了这种方法,只是用grep而不是nchar

标签: r timestamp lubridate


【解决方案1】:

如果原始数据中完全缺少“00:00:00”,您可以使用 grep 查找这些情况,然后在使用 ymd_hms() 或 mdy_hm() 之前粘贴“00:00:00” ) 函数。

第一种情况,日期/时间格式为 'YYYY-mm-dd HH:MM:SS':

#Before
test <- fread("time,  btc_price
2017-08-28 23:57:00, 4439.8163
2017-08-28 23:58:00, 4440.2363
2017-08-28 23:58:00, 4440.2363
2017-08-28 23:59:00, 4439.3313
2017-08-29         , 4439.6588
2017-08-29 00:01:00, 4440.3050")

test$time[grep("[0-9]{4}-[0-9]{2}-[0-9]{2}$",test$time)] <- paste(
  test$time[grep("[0-9]{4}-[0-9]{2}-[0-9]{2}$",test$time)],"00:00:00")

#After
print(test)

                  time btc_price
1: 2017-08-28 23:57:00  4439.816
2: 2017-08-28 23:58:00  4440.236
3: 2017-08-28 23:58:00  4440.236
4: 2017-08-28 23:59:00  4439.331
5: 2017-08-29 00:00:00  4439.659
6: 2017-08-29 00:01:00  4440.305

#Now you can use ymd_hms(as.character(df$date)) as usual.

第二种情况,日期/时间格式为'm/dd/yy HH:MM':

#Step 1 is to find/replace:
test <- fread("time,  btc_price
8/28/17 23:57, 4439.8163
8/28/17 23:57, 4440.2363
8/28/17 23:57, 4440.2363
8/28/17 23:57, 4439.3313
8/28/17      , 4439.6588
8/29/17 00:01, 4440.3050")

test$time[grep("[0-9]{1}/[0-9]{2}/[0-9]{2}$",test$time)] <- paste(
  test$time[grep("[0-9]{1}/[0-9]{2}/[0-9]{2}$",test$time)],"00:00"
)

print(test)
            time btc_price
1: 8/28/17 23:57  4439.816
2: 8/28/17 23:57  4440.236
3: 8/28/17 23:57  4440.236
4: 8/28/17 23:57  4439.331
5: 8/28/17 00:00  4439.659
6: 8/29/17 00:01  4440.305

#Step 2 is to adjust your mdy_hms() command; you need to leave off the 's':
#Ex. before:
mdy_hms(as.character("8/28/17 16:19"))
[1] NA
Warning message:
All formats failed to parse. No formats found. 

#After
test <- c("8/28/17 16:19","8/28/17 00:00")
mdy_hm(as.character(test))
[1] "2017-08-28 16:19:00 UTC" "2017-08-28 00:00:00 UTC"

一般来说,在 R 中将数字格式化为不带逗号也是一种好习惯;所以 4,439.3313 应该是 4439.3313。否则,R 可能会将其解释为列之间的逗号分隔。

【讨论】:

  • 请查看已编辑的问题,问题不在于btc_price 列(正在阅读中),而是date 列中缺少午夜的时间戳,这是抛出错误。
  • 我想你还是不明白。对于2017-08-29,您已经添加了时间戳00:00:00 UTC,但是如果您仔细查看我的问题,数据中就会缺少这一点-这是根本问题....如何在缺少时间戳的地方插入00:00:00从日期时间开始。
  • @zsad512 - 现在你已经澄清了问题,我已经编辑了我的答案。请参阅上面的更新。
  • 日期列为m/d/y 的第二个数据框呢?我仍然在那里遇到错误:All formats failed to parse
  • 我现在添加了完整的示例,从头到尾说明如何执行此操作。
猜你喜欢
  • 1970-01-01
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多