【问题标题】:Adding NA values for time gaps less than a certain time in R在 R 中为小于某个时间的时间间隙添加 NA 值
【发布时间】:2021-11-15 23:24:07
【问题描述】:

我有一个数据框(df;见下文),其中包含时间序列上的位置(多年,每小时给出位置)。数据中有很多差距,虽然我计划运行一个模型来估计一些缺失的位置,但我需要删除大于 10 小时的差距,因为我无法估计这段时间长度(即保持差距10 小时或更少)。

数据集没有这些日期时间间隔的 NA 值。因此,我必须首先为指定日期范围内缺失的每个日期时间创建 NA 行(数据为每年 9 月 1 日至 12 月 1 日),然后删除 NA 间隔大于 10 小时的行。

我将不得不使用不同的时间阈值和多个数据集来运行此分析。因此,是否可以只为特定的时间间隔大小添加 NA 值(为 10 小时或更短的时间间隔添加 NA),而不是将其设为两步过程?这样就无需消除超过 10 小时的时间间隔。

以下是一些示例数据:

table <- "id    date     time      lat       lon
1  A 2011-10-03 05:00:00 35.02957 -53.36053
2  A 2011-10-03 06:00:00 35.11430 -53.39990
3  A 2011-10-03 09:00:00 35.14563 -53.40357
4  A 2011-10-03 10:00:00 36.22431 -53.57891
5  A 2011-10-03 23:00:00 36.60950 -53.56792
6  B 2012-11-08 05:00:00 35.84570 -53.36992
7  B 2012-11-08 07:00:00 35.99980 -53.36084
8  B 2012-11-08 10:00:00 36.45001 -53.37093
9  B 2012-11-08 23:00:00 36.56789 -53.38654
10 B 2012-11-09 05:00:00 36.62456 -53.50901"

#Create a dataframe with above table
df <- read.table(text=table, header = TRUE)
df

这是预期的输出:

table2 <- "id    date     time      lat       lon
1  A 2011-10-03 05:00:00 35.02957 -53.36053
2  A 2011-10-03 06:00:00 35.11430 -53.39990
3  A 2011-10-03 07:00:00 NA       NA
4  A 2011-10-03 08:00:00 NA       NA
5  A 2011-10-03 09:00:00 35.14563 -53.40357
6  A 2011-10-03 10:00:00 36.22431 -53.57891
7  A 2011-10-03 23:00:00 36.60950 -53.56792
8  B 2012-11-08 05:00:00 35.84570 -53.36992
9  B 2011-11-08 06:00:00 NA       NA
10 B 2012-11-08 07:00:00 35.99980 -53.36084
11 B 2011-11-08 08:00:00 NA       NA
12 B 2011-11-08 09:00:00 NA       NA
13 B 2012-11-08 10:00:00 36.45001 -53.37093
14 B 2012-11-08 23:00:00 36.56789 -53.38654
15 B 2011-11-09 00:00:00 NA       NA
16 B 2011-11-09 01:00:00 NA       NA
17 B 2011-11-09 02:00:00 NA       NA
18 B 2011-11-09 03:00:00 NA       NA
19 B 2011-11-09 04:00:00 NA       NA
20 B 2012-11-09 05:00:00 36.62456 -53.50901"

#Create a dataframe with the above table
expected <- read.table(text=table2, header = TRUE)
expected

编辑:

我应该补充一点,这段代码还需要考虑存在不同的 ID,并且应该分别考虑每个 ID 的时间间隔,而不是所有 ID(例如,不应在第 5 行和第 6 行之间添加时间间隔,因为是两个不同 ID 之间的时间间隔)。

编辑 2:

Ronak Shah 的回答很有效。但是,有时我还必须使用几分钟来运行此代码。例如,时间间隔将是每 30 分钟一次,我希望保持 1 小时/60 分钟的间隔(两个 30 分钟的间隔),但不能超过这个间隔。是否可以为此调整 Ronak Shah 的答案?

我尝试将单位更改为“分钟”,将 >10 更改为 ">60",并将“小时”留在第二行,但这只是给了我间隔中每个小时的 NA 行,当我真的希望每 30 分钟间隔一个 NA,除非在那一小时内有两个以上的 30 分钟间隔。我也尝试了其他迭代,这给我留下了很多 NA,而我真的只想要每 30 分钟一次,而且只有一个小时或更短的间隔。

df %>%
  unite(datetime, date, time, sep = ' ') %>%
  mutate(datetime = lubridate::ymd_hms(datetime)) %>%
  group_by(id) %>%
  group_by(grp = cumsum(difftime(datetime, lag(datetime, default = first(datetime)), units = 'mins') > 60), .add = TRUE) %>%
  complete(datetime = seq(min(datetime), max(datetime), by = 'hour')) %>%
  ungroup %>%
  select(-grp)

【问题讨论】:

    标签: r time time-series na


    【解决方案1】:

    这是一种使用dplyrtidyr 的方法。

    结合datetime 列为每个id 创建日期时间创建一个grp 列,为10 小时内的时间值创建一个新组。使用complete 在每个组的最短和最长时间之间创建缺失的小时序列。

    library(dplyr)
    library(tidyr)
    
    df %>%
      unite(datetime, date, time, sep = ' ') %>%
      mutate(datetime = lubridate::ymd_hms(datetime)) %>%
      group_by(id) %>%
      group_by(grp = cumsum(difftime(datetime, lag(datetime, default = first(datetime)), units = 'hours') > 10), .add = TRUE) %>%
      complete(datetime = seq(min(datetime), max(datetime), by = 'hour')) %>%
      ungroup %>%
      select(-grp)
    
    #   id    datetime              lat   lon
    #   <chr> <dttm>              <dbl> <dbl>
    # 1 A     2011-10-03 05:00:00  35.0 -53.4
    # 2 A     2011-10-03 06:00:00  35.1 -53.4
    # 3 A     2011-10-03 07:00:00  NA    NA  
    # 4 A     2011-10-03 08:00:00  NA    NA  
    # 5 A     2011-10-03 09:00:00  35.1 -53.4
    # 6 A     2011-10-03 10:00:00  36.2 -53.6
    # 7 A     2011-10-03 23:00:00  36.6 -53.6
    # 8 B     2012-11-08 05:00:00  35.8 -53.4
    # 9 B     2012-11-08 06:00:00  NA    NA  
    #10 B     2012-11-08 07:00:00  36.0 -53.4
    #11 B     2012-11-08 08:00:00  NA    NA  
    #12 B     2012-11-08 09:00:00  NA    NA  
    #13 B     2012-11-08 10:00:00  36.5 -53.4
    #14 B     2012-11-08 23:00:00  36.6 -53.4
    #15 B     2012-11-09 00:00:00  NA    NA  
    #16 B     2012-11-09 01:00:00  NA    NA  
    #17 B     2012-11-09 02:00:00  NA    NA  
    #18 B     2012-11-09 03:00:00  NA    NA  
    #19 B     2012-11-09 04:00:00  NA    NA  
    #20 B     2012-11-09 05:00:00  36.6 -53.5
    

    【讨论】:

    • 谢谢!这完美地工作。有时我还必须使用几分钟来运行此代码。例如,时间间隔将是每 30 分钟一次,我希望保持 1 小时/60 分钟的间隔(两个 30 分钟的间隔),但不能超过这个间隔。是否可以为此进行调整?我已经尝试将单位更改为“分钟”,将 >10 更改为“>60”,并将“小时”留在第二行,但这只是在我真正想要的时候为间隔中的每个小时提供一条 NA 线每 30 分钟间隔一个 NA,除非该小时内有两个以上的 30 分钟间隔。这有意义吗?
    • 我已经编辑了我的问题,也提出了这个问题
    • @jl748795 为此,您需要更改两件事。 1) group_by(grp = cumsum(difftime(datetime, lag(datetime, default = first(datetime)), units = 'mins') &gt; 30), .add = TRUE) 2) complete(datetime = seq(min(datetime), max(datetime), by = '30 mins'))
    • 谢谢!这适用于获得 30 分钟的 NA 集,但我仍然有大于 1 小时的间隙(即连续四个 30 分钟的 NA,而不是以两个 30 分钟的间隔限制它。我希望将其合并到此代码中为了更容易以不同的时间间隔运行它,但我想它可以在之后完成。
    猜你喜欢
    • 2018-02-16
    • 1970-01-01
    • 2022-01-22
    • 2021-07-17
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多