Получить скользящее среднее на основе времени - PullRequest
0 голосов
/ 15 января 2019

У меня большой набор данных с двумя переменными - временем и значением. Мне нужно создать новый набор данных со скользящим средним для каждой строки, который вычисляет среднее значение всех значений за последние 60 минут (включая текущую строку).

Я попробовал несколько вещей, используя tq_mutate и другие, но не смог сделать это правильно.

Это пример данных:

data= structure(list(time= structure(c(1407626653, 1407626709, 
1407629849, 1407629927, 1407630463, 1407631433), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), value= c(4, 1, 4, 3, 2, 3
)), .Names = c("time", "value"), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

Это ожидаемый результат:

data = structure(list(time = structure(c(1407626653, 1407626709, 1407629849, 
1407629927, 1407630463, 1407631433), class = c("POSIXct", "POSIXt"
), tzone = "UTC"), value = c(4, 1, 4, 3, 2, 3), expected = c(4, 
2.5, 3, 3, 3, 3)), .Names = c("time", "value", "expected"), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

1 Ответ

0 голосов
/ 15 января 2019

Большинство подходов, которые вы увидите, включают в себя как-то заполнение данных большим количеством нулей / NA и использование rollapply / rollmean (которые основаны на # окнах наблюдений, а не на промежутке времени, хотя rollapply позволяет вам предоставлять пользовательские размеры окон (с точки зрения наблюдений) на наблюдение).

Пакет data.table позволяет вам сделать это эффективно, присоединив таблицу к самому столбцу времени так, чтобы мы рассматривали только предыдущий час.

library(data.table)
library(lubridate) # <-- only need for `- hours(1)` convenience, not strictly necessary
                   # Could instead do `- 60*60` and not load this package

setDT(data)[                                            #<Turn `data` in to a `data.table`
    J(end=unique(time), start=unique(time) - hours(1)), #<Define the start time=1 hour ago
                                                        #   and end time=current time.
    on=.(time <= end, time >= start),                   #<Join to itself restricting the
                                                        #   time to be within these windows
    list(value = mean(value)),                          #<Calc avg value
    by=.EACHI                                           #<For each join group (time window)
][,
    list(time, value)                                   #<Select the desired columns out
]                                                       # (o'wise you will get two
                                                        # identical "time" columns)

# output
                  time value
                <POSc> <num>
1: 2014-08-09 23:24:13   4.0
2: 2014-08-09 23:25:09   2.5
3: 2014-08-10 00:17:29   3.0
4: 2014-08-10 00:18:47   3.0
5: 2014-08-10 00:27:43   3.0
6: 2014-08-10 00:43:53   3.0

Существуют также другие варианты, такие как простое кодирование «для каждой строки, поиск всех строк со временем в пределах 1 часа от моего текущего времени и вычисление среднего значения» - они просто будут немного «ручными», как это решение есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...