【问题标题】:Timeseries average based on a defined time interval (bin)基于定义的时间间隔 (bin) 的时间序列平均值
【发布时间】:2018-02-17 01:20:34
【问题描述】:

这是我的数据集的一个示例。我想每 10 秒根据时间(即 ts)计算 bin 平均值。您能否提供一些提示以便我继续?

就我而言,我想平均每 10 秒的时间 (ts) 和 Var。例如,我会得到一个 Var 和 ts 从 0 到 10 秒的平均值;我将在 11 到 20 秒等范围内得到另一个 Var 和 ts 的平均值。

 df = data.frame(ts = seq(1,100,by=0.5), Var = runif(199,1, 10))

我可以使用 R 中的任何函数或库来完成这项任务吗?

【问题讨论】:

  • 您可以使用cut 函数来划分您的时间rdocumentation.org/packages/base/versions/3.4.3/topics/cut
  • 这称为“合并平均”
  • @PaulH: cut 是矫枉过正,当一个简单的group_by(interval=round(df$ts/10)) 将完成这项工作......
  • @smci 绝招。那么cut 什么时候不会矫枉过正呢?
  • @PaulH:我想我们什么时候想要传入自定义中断(或标签)。像非均匀中断,例如分位数,或您能想到的任何其他非均匀中断。

标签: r time-series mean binning


【解决方案1】:

有很多方法可以计算分箱平均值:使用基础 aggregateby、使用包 dplyrdata.table,可能使用 zoo,当然还有其他时间序列包...

library(dplyr)
df %>%
    group_by(interval = round(df$ts/10)*10) %>%
    summarize(Var_mean = mean(Var))
# A tibble: 11 x 2
   interval Var_mean
      <dbl>    <dbl>
 1        0 4.561653
 2       10 6.544980
 3       20 6.110336
 4       30 4.288523
 5       40 5.339249
 6       50 6.811147
 7       60 6.180795
 8       70 4.920476
 9       80 5.486937
10       90 5.284871
11      100 5.917074

这就是 dplyr 方法,看看它和 data.table 是如何让你命名中间变量的,这样可以保持代码的清晰易读。

【讨论】:

  • 似乎 OP 希望将间隔报告为例如 0 - 10、10 - 20。报告为 1、2、3 的间隔......感觉有误导性
  • @PaulH:当然,通过乘以除数来简单地添加:round(df$ts/10)*10
  • @smci 如何将您的方法应用于多个列?例如,根据分箱 ts 计算 ts、Var1、Var2 和 Var3 每一列的均值。示例如下: df = data.frame(ts = seq(1,100,by=0.5), Var1 = runif(199,1, 10), Var2 = runif(199,1, 10), Var3 = runif(199, 1, 10))
  • @Kuo-HsienChang: summarize(ts_mean = mean(ts), Var1_mean = mean(Var1), Var2_mean = mean(Var2), ...) 都在文档中。
【解决方案2】:

假设问题中的df,转换为动物园对象,然后聚合。

aggregate.zoo 的第二个参数是一个与时间向量长度相同的向量,给出每个原始时间要映射到的新时间。第三个参数适用于其时间已映射到相同值的所有时间序列值。这种映射可以通过多种方式完成,但这里我们选择使用 10 * ceiling(time(z) / 10) 将时间 (0, 10] 映射到 10,(10, 20] 到 20 等)。

鉴于答案中的其他一些 cmets,让我指出,与使用数据框相比,这里有显着的简化,首先是因为数据已被缩减为一维(与数据中的 2 维相比)。框架),其次是因为它更有利于整个对象的方法,而使用数据帧需要不断地挑选对象并处理这些部分,第三是因为现在拥有动物园的所有设施来操纵时间序列,例如众多NA 去除方案、滚动函数、重载算术运算符、n 路合并、简单访问经典、晶格和 ggplot2 图形,design 强调与基本 R 的一致性,使其易于学习和广泛的文档,包括 5 vignettes plus help files 和大量示例考虑到 14 年的开发和广泛使用,错误可能很少。

library(zoo)
z <- read.zoo(df)

z10 <- aggregate(z, 10 * ceiling(time(z) / 10), mean)

给予:

> z10
      10       20       30       40       50       60       70       80 
5.629926 6.571754 5.519487 5.641534 5.309415 5.793066 4.890348 5.509859 
      90      100 
4.539044 5.480596 

(请注意,问题中的数据不可重复,因为它使用了没有set.seed 的随机数,因此如果您尝试重复上述操作,您将不会得到相同的答案。)

现在我们可以使用以下任何一种来绘制它:

plot(z10)

library(lattice)
xyplot(z10)

library(ggplot2)
autoplot(z10)

【讨论】:

    【解决方案3】:

    总的来说,我同意@smci,dplyrdata.table 方法在这里是最好的。让我进一步详细说明。

    # the dplyr way
    library(dplyr)
    df %>% 
      group_by(interval = ceiling(seq_along(ts)/20)) %>% 
      summarize(variable_mean = mean(Var))
    
    # the data.table way
    library(data.table)
    dt <- data.table(df)
    dt[,list(Var_mean = mean(Var)),
       by =  list(interval = ceiling(seq_along(dt$ts)/20))]
    

    我不会在这里使用 tszooxts 这样的传统时间序列解决方案。他们的方法更适合处理常规频率和频率,例如月度或季度数据。除了ts,它们还可以处理不规则频率和高频数据,但许多方法(例如打印方法)效果不佳,或者至少不会给您带来优于data.tabledata.frame 的优势。

    只要您只是对data.tabledplyr 进行聚合和分组,在性能方面也可能更快。猜猜data.table 在速度方面比dplyr 有优势,但你会有基准/配置文件,例如使用microbenchmark。因此,如果您无论如何都没有使用经典的 R 时间序列格式,则没有理由使用这些进行聚合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-04
      • 1970-01-01
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-12
      • 2016-04-05
      相关资源
      最近更新 更多