当格式不同时如何使用 R 计算时间差(以毫秒为单位)?

How to calculate time difference in milliseconds using R when formats are different?

我在 R 中遇到了一个让我很烦的问题!你能帮帮我吗?

我在 Whosebug 中发现了一个问题,它给了我很好的解释。

这里是link:How to parse milliseconds?

我能够实现以下运行良好的代码。

z2 <- strptime("10/2/20 11:16:17.682", "%d/%m/%y %H:%M:%OS")
z1 <- strptime("10/2/20 11:16:16.683", "%d/%m/%y %H:%M:%OS")

当我计算 z2-z1 时,我得到 时差0.9989998秒

同样,当我使用

z3 <- strptime("130 11:16:16.683", "%j %H:%M:%OS")
z4 <- strptime("130 11:16:18.682", "%j %H:%M:%OS")

当我计算 z4-z3 时,我得到 时差1.999秒

我的问题是什么?

第一列的格式为 130 18:25:50.408,有数百万行!!!
第二列的格式 2020 130 18:25:51.357 与第一列类似,但年份为 2020.

第一列也是 2020 年,但由于年份不存在,R 使用当前年份。

第一个问题,

如何减去两列?我知道如何减去列。

不知道的是减去这两次

比如第二次是2020 13018:25:51.357 第一次是 130 18:25:50.408

我想我可以通过编程将其转换为字符串,并消除 2020。但是,我希望可以使用 base R 或 获得更快的解决方案lubridate 包。

第二个问题,

"%j %H:%M:%OS"130 11:16:16.683

的格式

2020 130 18:25:51.357的格式是什么?

正如之前所解释的,这工作得很好:

z3 <- strptime("130 11:16:16.683", "%j %H:%M:%OS")

但是,这不起作用。

z7 <- strptime("2020 130 11:16:16.683", "%y %j %H:%M:%OS")

更新 1

我解决了第二个问题!

但是第一个问题我还没想好

第二个问题,格式错误是%y不是写成大写的%Y

这是一个例子:

later <- strptime("2020 130 11:16:17.683", "%Y %j %H:%M:%OS")
earlier <- strptime("2020 130 11:16:16.684", "%Y %j %H:%M:%OS")
difftime(later,earlier,units="secs")

R 结果是:

时差0.9990001秒

更新 2

此时,待处理的是:

我需要减去 2020 年同一天制作的两次。

第二次有年份,第一次没有。

later <- strptime("2020 130 11:16:17.683", "%Y %j %H:%M:%OS")
earlier <- strptime("130 11:16:16.684", "%j %H:%M:%OS")
difftime(later,earlier,units="secs")

R 产生以下结果: 时差-31622399秒

为什么?正如我们在 2021 年,R 将向量 earlier 格式化为当前年份,即 2021,因为年份不存在。

我的专栏有数百万行。

在这一点上,我的猜测是我需要添加 2020 并进行串联或类似的操作。还有其他方法吗?

感谢您的帮助!

您的对象 z2 是一个 POSIX 列表对象。这意味着它是您时间的时间元素列表。

print.default(z2)
# $sec
# [1] 17.682
# 
# $min
# [1] 16
# 
# $hour
# [1] 11
# 
# $mday
# [1] 10
# 
# $mon
# [1] 1
# 
# $year
# [1] 120
# 
# $wday
# [1] 1
# 
# $yday
# [1] 40
# 
# $isdst
# [1] 0
# 
# $zone
# [1] "GMT"
# 
# $gmtoff
# [1] NA
# 
# attr(,"class")
# [1] "POSIXlt" "POSIXt"

当你做减法时,z2 - z1 R 将此操作分派给一个名为 -.POSIXt 的函数,该函数本身调用 difftime。此函数将 z2 转换为 POSIX 计数对象。这意味着它被转换为自纪元开始以来的秒数,默认情况下为“1970-01-01”。

options("digits" = 16)
print.default(as.POSIXct(z2))
# [1] 1581333377.682
# attr(,"class")
# [1] "POSIXct" "POSIXt" 
# attr(,"tzone")
# [1] ""
difftime(z2, z1)
# Time difference of 0.9989998340606689 secs

R 与大多数软件一样,适用于 double precision 数字。这意味着算术是不精确的,尽管近似正确。大多数软件会尝试通过减少显示的位数来隐藏这种不精确性。也就是说,不同的数字会给你不同的不精确性,所以你可能更喜欢直接引用 z2 的列表元素。

print.default(z2$sec - z1$sec)
# [1] 0.9989999999999988

因此,您可以使用自己喜欢的 data.frame 工具应用时差。

options("digits" = 6)
# character columns
df1 <- data.frame(
    col1 = c("10/2/20 11:16:17.682", "10/2/20 11:16:16.683"), 
    col2 = c("130 11:16:16.683", "130 11:16:18.682"), 
    stringsAsFactors = FALSE)
library(dplyr)
# convert columns to POSIXlt
df2 <- mutate(df1, 
    col1 = strptime(col1, "%d/%m/%y %H:%M:%OS"), 
    col2 = strptime(stringr::str_c("2020 ", col2), "%Y %j %H:%M:%OS"), 
    diff_days = unclass(difftime(col2, col1, units = "days")))
df2
# col1                col2                  diff_days
# 1 2020-02-10 11:16:17 2020-05-09 11:16:16   88.9583
# 2 2020-02-10 11:16:16 2020-05-09 11:16:18   88.9584