【问题标题】:10-min moving average to 1-hour moving average in RR中的10分钟移动平均线到1小时移动平均线
【发布时间】:2018-10-21 01:34:41
【问题描述】:

我有一组 10 分钟移动平均的天气数据,以 1 分钟的间隔显示。我想将其转换为 1 小时平均值。

               Date   Direction   Speed
1  2017-07-06 00:01:00        93   7.3
2  2017-07-06 00:02:00        92   7.4
3  2017-07-06 00:03:00        92   7.3
4  2017-07-06 00:04:00        91   7.4
5  2017-07-06 00:05:00        91   7.3
6  2017-07-06 00:06:00        91   7.3
7  2017-07-06 00:07:00        91   7.2
8  2017-07-06 00:08:00        90   7.1
9  2017-07-06 00:09:00        90   6.9
10 2017-07-06 00:10:00        91   6.7
...
(thousands of row of data in 1 min-interval

* 以上方向和速度为 10 分钟移动平均线

对于正常的移动平均内置函数,它们会遇到每个邻域值,例如:

rollmean(timeLine$Speed, 60, fill=FALSE, align = "right")

将在遇到 n、n-1、n-2、n-3、...、n-59 的每个值上产生滚动平均值。

但是,由于我的原始数据已经是 10 分钟的平均值,我只需取值 n、n-10、n-20、n-30、n-40、n-50 即可将其转换为每小时平均值。

例如,如果我想要 2001-07-06 10:00:00 的每小时数据,我只需对以下各项取平均值:

  • 2001-07-06 10:00:00
  • 2001-07-06 09:50:00
  • 2001-07-06 09:40:00
  • 2001-07-06 09:30:00
  • 2001-07-06 09:20:00
  • 2001-07-06 09:10:00

有什么方法可以让我在 R 上顺利计算吗?

提前感谢您的帮助!

更新 1:这是 dput(head(timeLine, 10))

structure(
  list(
    Date = structure(c(1499270460, 1499270520, 1499270580, 1499270640, 1499270700, 1499270760, 1499270820, 1499270880, 1499270940, 1499271000),
    class = c("POSIXct", "POSIXt"), tzone = "Asia/Hong_Kong"), 
  Direction = c(93L, 92L, 92L, 91L, 91L, 91L, 91L, 90L, 90L, 91L),
  Speed = c(7.3, 7.4, 7.3, 7.4, 7.3, 7.3, 7.2, 7.1, 6.9, 6.7)),
  .Names = c("Date", "Direction", "Speed"),
  row.names = c(NA, 10L),
  class = "data.frame")

【问题讨论】:

  • 你应该发布 dput(timeLine) 的输出,因为它是一个 data.table 对象;至少它prints 像一个。发布 print 表示形式使其成为一种 PITA 以使其正确解析。即使是非常灵活的 fread 函数也会给你 5 列,而你显然只有 3 列。遗憾的是,POSIXt 列的默认打印输出有空格。
  • 感谢您的建议。 dput(head(timeLine, 10)) 的输出是 structure(list(Date = structure(c(1499270460, 1499270520, 1499270580, 1499270640, 1499270700, 1499270760, 1499270820, 1499270880, 1499270940, 1499271000), class = c("POSIXct", "POSIXt"), tzone = "Asia/Hong_Kong"), Direction = c(93L, 92L, 92L, 91L, 91L, 91L, 91L, 90L, 90L, 91L), Speed = c(7.3, 7.4, 7.3, 7.4, 7.3, 7.3, 7.2, 7.1, 6.9, 6.7)), .Names = c("Date", "Direction", "Speed"), row.names = c(NA, 10L), class = "data.frame")

标签: r moving-average


【解决方案1】:

rollapplyr(末尾的r 表示右对齐)在动物园中允许使用width = list(offset_vector) 指定偏移量,如下所示:

transform(timeLine, avg = rollapplyr(Speed, list(seq(-50, 0, 10)), mean, fill = NA))

【讨论】:

  • 嵌套简单! align="right" 在你的陈述中变成假人了吗?谢谢
  • 是的,rollapplyr 最后带有r 使用align="right"。
【解决方案2】:

嗯,几乎可以肯定有一种更优雅的方式,但我认为这是可行的。我使用了lubridate 包来轻松转换为日期时间格式:

library(tidyverse)
library(lubridate)

df = read.csv(text="
              Date,Time,Direction,Speed
              2001-07-04,09:01:00,310,4.0
              2001-07-04,09:02:00,310,3.9
              2001-07-04,09:03:00,310,3.9
              2001-07-04,09:04:00,310,3.9
              2001-07-04,09:05:00,300,3.9
              2001-07-04,09:06:00,300,4.0
              2001-07-04,09:07:00,300,3.9
              2001-07-04,09:08:00,300,4.0
              2001-07-04,09:09:00,300,4.0
              2001-07-04,09:10:00,300,4.0
              2001-07-04,09:11:00,290,4.0
              2001-07-04,09:12:00,290,4.0
              2001-07-04,09:13:00,290,4.0
              2001-07-04,09:14:00,290,4.0
              2001-07-04,09:15:00,290,4.0", sep=",", header = TRUE, row.names = NULL)

lagged_avg = function(col) {
  lag_positions = c(0,10,20,30,40,50)
  sum = 0
  for (n in lag_positions) {
    sum = sum + lag(col, n)
  }
  return(sum/6)
}

df = df %>%
  mutate(datetime = ymd_hms(paste0(Date," ",Time))) %>%
  mutate(lag = lagged_avg(Speed)) %>%
  select(-Date, -Time)

【讨论】:

    【解决方案3】:

    我会查看tibbletime package - 具体来说,collapse_by() 功能很有帮助。以下应该有效(使用更多数据更容易测试):

    library(tidyverse)
    library(lubridate)
    library(tibbletime)
    
    tbl_time(timeLine, index = Date) %>%
      filter(minute(Date) %in% seq(0, 50, 10)) %>%
      collapse_by("hour", clean = TRUE) %>%
      group_by(Date) %>%
      summarise_all(mean)
    

    注意:根据您对工作时间的看法,您可能需要将collapse_by 行更改为collapse_by("hour", clean = TRUE, side = "start") - 默认情况下,它将使用side = "end"。

    【讨论】:

      【解决方案4】:

      解决方案是首先过滤0, 10, 20, 30, 40, 50th 分钟数据。可以将日期/时间的minute 除以10 并检查remainder 是否等于0 以过滤0, 10, 20, 30, 40, 50th 分钟数据的数据。每 6 个观察值应用 zoo::rollmean。这样,每小时的平均值将使用第 10 分钟、第 20 分钟、第 30 分钟、第 40 分钟、第 50 分钟和第 0 分钟数据计算。最后过滤minute == 0(一个小时)。

      library(zoo)
      library(lubridate)
      library(tidyverse)
      
      timeLine_mod %>% filter(minute(Date) %% 10 == 0) %>%
      mutate(meanSpeed = rollmean(Speed, 6, fill = FALSE, align = "right")) %>%
      filter(minute(Date) == 0)
      
      #                  Date Direction Speed meanSpeed
      # 1 2017-07-06 01:00:00        91   6.7       6.7
      # 2 2017-07-06 02:00:00        91   6.7       6.7
      # 3 2017-07-06 03:00:00        91   6.7       6.7
      

      数据: 由于 OP 仅提供 10 分钟的数据,不足以计算每小时平均值。因此,我将数据扩展至 3 小时:

      timeLine <- structure(list(Date = structure(c(1499270460, 1499270520, 1499270580, 
      1499270640, 1499270700, 1499270760, 1499270820, 1499270880, 1499270940, 1499271000), 
      class = c("POSIXct", "POSIXt"), tzone = "Asia/Hong_Kong"), 
      Direction = c(93L, 92L, 92L, 91L, 91L, 91L, 91L, 90L, 90L, 91L), 
      Speed = c(7.3, 7.4, 7.3, 7.4, 7.3, 7.3, 7.2, 7.1, 6.9, 6.7)), 
      .Names = c("Date", "Direction", "Speed"), row.names = c(NA, 10L), 
      class = "data.frame")
      
      #Extend data to cover 3 hours as
      timeLine_mod <- timeLine %>% complete(Date = seq(min(Date),
               min(Date)+60*60*3-60,by="1 min"))
      
      #Repeat the value of Direction and Speed
      timeLine_mod$Direction <- timeLine$Direction
      timeLine_mod$Speed <- timeLine$Speed
      

      【讨论】:

      • 它将成为按小时间隔滚动的小时平均值,但不是 1 分钟间隔
      • @TLee 我想你已经提到你得到的数据已经是每分钟显示的 10 分钟移动平均线。也许这就是您在第一行问题中所写的。但如果你还没有,那么首先计算 10 分钟移动平均线,然后再计算我提到的解决方案。也许你可以在单管中做到这一点。
      猜你喜欢
      • 2017-09-01
      • 2023-03-12
      • 2013-12-22
      • 2016-05-16
      • 2022-01-26
      • 1970-01-01
      • 2011-06-29
      • 2019-04-24
      • 2012-05-24
      相关资源
      最近更新 更多