如何重写一个 R 循环,将每 15 次观察的平均值取到相同的代码但没有循环

How to rewrite an R loop taking averages of every 15 observations to same code but without a loop

我正在处理一个巨大的数据集(多年的 1 分钟间隔的能源使用观察)。我想将它从 1 分钟间隔转换为 15 分钟间隔。

我写了一个 for 循环,它成功地做到了这一点(在一小部分数据上测试过);然而,当我在主数据上尝试 运行ning 时,它执行得非常慢 - 我需要 175 多个小时才能 运行 完整循环(我在执行中途停止了它)。

转换为第15分钟间隔的数据为千瓦时使用量;因此,转换它只需要取前 15 个观察值的平均值,然后取第二个 15 个观察值的平均值,依此类推。这是有效的循环:

# Opening the file
data <- read.csv("1.csv",colClasses="character",na.strings="?")

# Adding an index to each row
total <- nrow(data)
data$obsnum <- seq.int(nrow(data))

# Calculating 15 min kwH usage
data$use_15_min <- data$use
for (i in 1:total) {
  int_used <- floor((i-1)/15)
  obsNum <- 15*int_used
  sum <- 0
  for (j in 1:15) {
    usedIndex <- as.numeric(obsNum+j)
    sum <- as.numeric(data$use[usedIndex]) + sum
  }
  data$use_15_min[i] <- sum/15
}

我一直在寻找一个可以做同样事情但不使用循环的函数,我想这应该会节省很多时间。然而,我一直没能找到一个。不使用循环如何实现相同的功能?

尝试 data.table:

library(data.table)

DT <- data.table(data)
n <- nrow(DT)
DT[, use_15_min := mean(use), by = gl(n, 15, n)]

备注

问题缺少输入数据,所以我们使用了这个:

data <- data.frame(use = 1:100)

一个潜在的解决方案是计算 运行 均值(例如使用 TTR::runMean),然后每 15 个观察值 select。这是一个例子:

df = data.frame(x = 1:100, y = runif(100))
df['runmean'] = TTR::runMean(df['y'], n=15)
df_15 = df[seq(1,nrow(df), 15), ]

我无法测试它,因为我没有您的数据,但也许:

total <- nrow(data)
data$use_15_min = TTR::runMean(data$use, n=15)
data_15_min = data[seq(1, nrow(df), 15)]

我会使用 lubridate::floor_date 创建 15 分钟的分组。

library(tidyverse)
library(lubridate)

df <- tibble(
  date = seq(ymd_hm("2019-01-01 00:00"), by = "min", length.out = 60 * 24 * 7),
  value = rnorm(n = 60 * 24 * 7)
)

df
#> # A tibble: 10,080 x 2
#>    date                  value
#>    <dttm>                <dbl>
#>  1 2019-01-01 00:00:00  0.182 
#>  2 2019-01-01 00:01:00  0.616 
#>  3 2019-01-01 00:02:00 -0.252 
#>  4 2019-01-01 00:03:00  0.0726
#>  5 2019-01-01 00:04:00 -0.917 
#>  6 2019-01-01 00:05:00 -1.78  
#>  7 2019-01-01 00:06:00 -1.49  
#>  8 2019-01-01 00:07:00 -0.818 
#>  9 2019-01-01 00:08:00  0.275 
#> 10 2019-01-01 00:09:00  1.26  
#> # ... with 10,070 more rows

df %>%
  mutate(
    nearest_15_mins = floor_date(date, "15 mins")
  ) %>%
  group_by(nearest_15_mins) %>%
  summarise(
    avg_value_at_15_mins_int = mean(value)
  )
#> # A tibble: 672 x 2
#>    nearest_15_mins     avg_value_at_15_mins_int
#>    <dttm>                                 <dbl>
#>  1 2019-01-01 00:00:00                  -0.272 
#>  2 2019-01-01 00:15:00                  -0.129 
#>  3 2019-01-01 00:30:00                   0.173 
#>  4 2019-01-01 00:45:00                  -0.186 
#>  5 2019-01-01 01:00:00                  -0.188 
#>  6 2019-01-01 01:15:00                   0.104 
#>  7 2019-01-01 01:30:00                  -0.310 
#>  8 2019-01-01 01:45:00                  -0.173 
#>  9 2019-01-01 02:00:00                   0.0137
#> 10 2019-01-01 02:15:00                   0.419 
#> # ... with 662 more rows