【问题标题】:Extract data by minimum time interval between observations in a time series按时间序列中观测值之间的最小时间间隔提取数据
【发布时间】:2019-10-21 06:14:59
【问题描述】:

我有很长的一组从动物发射器收集的数据。由于发射机的太阳能电池的充电方式不同,数据点之间的时间间隔变化很大(从 180 秒到超过一小时不等)。我想对数据进行子集化,因此点之间的间隔至少为 10 分钟或 600 秒。

这是我的一小部分数据的样子:

    datetime             id
    01/09/2015 14:10:54  A
    01/09/2015 14:26:56  A
    01/09/2015 14:41:28  A
    01/09/2015 14:43:53  A
    01/09/2015 14:46:37  A
    01/09/2015 14:48:57  A
    01/09/2015 14:51:31  A
    01/09/2015 14:54:08  A
    04/09/2015 14:37:07  B
    04/09/2015 14:52:07  B
    04/09/2015 15:07:04  B
    04/09/2015 15:15:35  B
    04/09/2015 15:18:00  B
    04/09/2015 15:20:23  B
    04/09/2015 15:22:49  B
    04/09/2015 15:25:12  B 
    04/09/2015 15:28:52  B

我希望输出的最短间隔为 10 分钟:

    datetime             id
    01/09/2015 14:10:54  A
    01/09/2015 14:26:56  A
    01/09/2015 14:41:28  A
    01/09/2015 14:51:31  A
    01/09/2015 14:37:07  B
    04/09/2015 14:52:07  B
    04/09/2015 15:07:04  B
    04/09/2015 15:18:00  B 
    04/09/2015 15:28:52  B

我发现了一个几乎完全相同的问题,答案是here。他们的数据包括 id、日期和时间。这是答案中给出的代码:

    library(dplyr)
    library(lubridate)

    locdata %>% 
       mutate(timestamp = dmy_hm(paste(date, time))) %>%
       group_by(id, date) %>%
       mutate(delta = timestamp - first(timestamp),
       steps = as.numeric(floor(delta / 3600)), 
       change = ifelse(is.na(steps - lag(steps)), 1, steps - lag(steps))) %>%
          filter(change > 0) %>%
          select(id, date, timestamp)

我对我的数据稍作了调整,如下所示:

    result <- mydata %>%
                group_by(id) %>%                          
                mutate(delta = datetime - first(datetime),        
                steps = as.numeric(floor(delta / 600)),
                change = ifelse(is.na(steps - lag(steps)), 1, steps - lag(steps)))

代码结果如下:

    datetime             id    delta   steps   change
    01/09/2015 14:10:54  A     0        0      1
    01/09/2015 14:26:56  A     962      1      1
    01/09/2015 14:41:28  A     1834     3      2
    01/09/2015 14:51:31  A     2437     4      1
    04/09/2015 14:37:07  B     0        0      1
    04/09/2015 14:52:07  B     900      1      1
    04/09/2015 15:07:04  B     1797     2      1
    04/09/2015 15:15:35  B     2308     3      1
    04/09/2015 15:18:00  B     2453     4      1
    04/09/2015 15:22:29  B     3105     5      1

输出给出从零时间开始的每 10 分钟时间块中的第一个数据点(每个 id)。这不完全是我需要的,因为一些时间点相隔不到 10 分钟。我需要的是下一次 在每个 id 内的上一点之后 10 分钟或更长时间

知道我该怎么做吗?我需要使用循环吗?感谢您的任何想法。

【问题讨论】:

  • 你能添加一个你的数据框的例子吗? dput(locdata[1:30, ]) 可以。
  • 感谢您的回复。这是我最初包含的 17 行数据; "","datetime","id" "1",2015-09-01 14:10:54,"A" "2",2015-09-01 14:26:56,"A" "3", 2015-09-01 14:41:28,"A" "4",2015-09-01 14:43:53,"A" "5",2015-09-01 14:46:37,"A" "6",2015-09-01 14:48:57,"A" "7",2015-09-01 14:51:31,"A" "8",2015-09-01 14:54:08 "A" "9",2015-09-04 14:37:07,"B" "10",2015-09-04 14:52:07,"B" "11",2015-09-04 15 :07:04,"B""12",2015-09-04 15:15:35,"B""13",2015-09-04 15:18:00,"B""14",2015- 09-04 15:20:23,"B""15",2015-09-04 15:22:49,"B""16",2015-09-04 15:25:12,"B""17 ",2015-09-04 15:28:52,"B"
  • @Istrel 这就是你的意思吗?这里只有 17 行,但如果需要我可以添加更多。再次感谢,并在下面的回复中查看我的 cmets。

标签: r loops datetime dplyr subset


【解决方案1】:

我有这个想法,使用 dplyr(带有 lead() 函数)和一个 while 循环,它可能会对你有所帮助

library(dplyr)
library(lubridate)

data <- data %>%
  mutate(date = lubridate::ymd_hms(datetime),
         id_rows = 1:nrow(.)) %>%
  group_by(id) %>%
  mutate(delta = lubridate::time_length(lag(date) %--% date, unit = "sec"))

while (min(data$delta, na.rm = T) < 600) {
  rm_rows <- data %>%
    filter(delta < 600) %>%
    filter(date == min(date)) %>%
    pull(id_rows)
  data <- data %>%
    filter(!id_rows %in% rm_rows) %>%
    mutate(delta = lubridate::time_length(lag(date) %--% date, unit = "sec"))
}

【讨论】:

  • 非常感谢您的回复。这段代码很棒,因为它返回 delta 作为 id 中每个连续行之间的差异。但是,它会删除 delta 值低于 600 的所有行,这会导致删除太多行。例如,当我在上面 17 行的测试数据集上运行代码时,它应该返回 9 时只返回 6 行。我认为我需要一个循环,如果 delta 低于 600,则删除下一行,然后重新开始。
  • 为了更清楚地说明上述观点,我需要它来计算第 1 行和第 2 行之间的 delta,而不是一次性计算每一行之间的 delta,然后删除所有 delta 低于 600 的那些,如果 delta 低于 600,则删除第 2 行,然后计算第 1 行和第 3 行之间的 delta。
  • 我编辑了答案,我使用了lead(),但在这里你想使用lag()。现在它返回 9 行
猜你喜欢
  • 2018-02-28
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
  • 1970-01-01
  • 2020-01-31
  • 1970-01-01
  • 2022-01-16
  • 2020-10-13
相关资源
最近更新 更多