【问题标题】:R: how to resample a datetime variable at the millisecond level?R:如何在毫秒级别重新采样日期时间变量?
【发布时间】:2017-05-15 02:33:58
【问题描述】:

我有一个如下的数据框

library(dplyr)
library(lubridate)
time = c('2013-01-03 22:04:21.549', '2013-01-03 22:04:21.549', '2013-01-03 22:04:21.559', '2013-01-03 22:04:23.559' )
value = c(1,2,3,4)

data <- data_frame(time, value)
data <-data %>%  mutate(time = ymd_hms(time))

# A tibble: 4 × 2
                     time value
                   <dttm> <dbl>
1 2013-01-03 22:04:21.549     1
2 2013-01-03 22:04:21.549     2
3 2013-01-03 22:04:21.559     3
4 2013-01-03 22:04:23.559     4

我想每 200 毫秒重新采样一次这个数据帧。

也就是说,每 200 毫秒取 value 的平均值。

我知道lubridate::floor_date(time, '1 second') 可以使用到second 精度,但不能用于milliseconds

在上面的示例中,行 123 应该组合在一起,而行 4 应该是单独的(注意它与其他行相距 2 秒)。

有什么想法吗? 谢谢!

【问题讨论】:

    标签: r datetime dplyr xts lubridate


    【解决方案1】:

    由于您使用了[xts] 标签,这里有一个 xts 解决方案:

    options(digits.secs=6)
    require(xts)
    x <- xts(1:4, as.POSIXct(c('2013-01-03 22:04:21.549', '2013-01-03 22:04:21.549',
                               '2013-01-03 22:04:21.559', '2013-01-03 22:04:23.559')))
    period.apply(x, endpoints(x, "ms", 200), mean)
    #                         [,1]
    # 2013-01-03 22:04:21.559    2
    # 2013-01-03 22:04:23.559    4
    

    从您的data 对象开始:

    x <- with(data, xts(value, time))
    period.apply(x, endpoints(x, "ms", 200), mean)
    

    【讨论】:

    • 非常干净!这里的一个困难是我需要使用 dplyr 进行分组(总是相同的原因.. 我需要在 datafeame 中保留混合变量类型)可以将使用 xts 构造的分组时间变量插入数据帧?
    • Joshua,您将如何从我的数据框开始调整您的解决方案?我的意思是,不是从头开始创建 xts?
    • @Noobie:查看我的编辑。从您的问题中不清楚您如何需要 groupby 使用 dplyr,所以我只能猜测您的用例。另请注意,由于dplyr::lag 掩盖了stats::lag 泛型,如果附加了dplyr,您将失去顶层的方法分派(即在xts 对象上调用lag 不会分派到xts:::lag.xts)。而且我不知道您的意思是,“可以将使用 xts 构造的分组时间变量插入数据帧吗?”。
    • 你好约书亚,首先新年快乐。我的意思是:如何使用xts::endpoints 在我的数据框中创建一个分组变量timegroup,以便我可以对该变量执行groupby(因此如果200 毫秒按组分组)?本质上,得到类似于另一个答案中的ms200mn 列。
    • @Noobie:你不能(很容易)。 xts::endpoints 用于 xts 对象。它只返回时间组的端点,而不是分组变量所需的(每个原始观察一个“组”观察)。
    【解决方案2】:

    您对 xts 解决方案的评论要求将其“重新插入”到数据框中,这一事实让我认为您要么想要一个合并的结果,要么想要一个按时间分组的列。这就是 ave 函数在 base R 中所做的。可能有一个 dplyr 等价物,但我更像是一个 base-R-guy: 编辑:

     data$ms200mn <- ave(data$value, 
                         cut( arg <- as.numeric(data$time) , 
                                    breaks=seq( floor(arg[1]), ceil(arg[4]), by=0.2) ),
                         FUN=mean)
    >  data
    # A tibble: 4 × 3
                     time value ms200mn
                   <dttm> <dbl>   <dbl>
    1 2013-01-03 22:04:21     1       2
    2 2013-01-03 22:04:21     2       2
    3 2013-01-03 22:04:21     3       2
    4 2013-01-03 22:04:23     4       4
    

    这并不是真正正确地称为“采样”(或重新采样),而是聚合seq.POSIXt-function 没有“msec”选项(因此需要转换为数字秒)并且不允许使用小数秒。

    解释:

    cut(arg <- as.numeric(data$time), breaks=seq( floor(arg[1]), ceil(arg[4]), by=0.2) )
    

    它是按从第一个项目以下开始到最后一个项目以上结束的一系列中断定义的组中的项目“分类”或“分类”。需要创建arg-值,因为(出于我不明白的原因)seq 函数可以使用无法使用的原始“日期时间”变量。

    【讨论】:

    • 谢谢,但我不明白这里发生了什么:ave(data$value, format(data$time, by= "3 sec"), FUN=mean) 给出了相同的结果
    • 那是因为我认为我的示例证明了小数秒是可以接受的。他们不是。我需要为 ave 提出一个不同的第二个参数。
    • 谢谢伙计。你能解释一下cut( arg &lt;as.numeric(data$time) , breaks=seq( floor(arg[1]), ceil(arg[4]), by=0.2) )在做什么吗?
    猜你喜欢
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    相关资源
    最近更新 更多