Как отфильтровать набор данных и быстрее вычислить новую переменную в R? - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть набор данных со значениями каждую минуту, и я хочу рассчитать среднее значение для каждого часа.Я попытался с помощью group_by (), filter () и Sumumize () из пакета dplyr, чтобы уменьшить данные каждый час.Когда я использую только эти функции, я могу получить среднее значение для каждого часа, но только для каждого месяца, и я хочу его для каждого дня.

> head(DF)
         datetime        pw        cu          year m  d hr min
1 2017-08-18 14:56:00 0.0630341 1.94065        2017 8 18 14  53
2 2017-08-18 14:57:00 0.0604653 1.86771        2017 8 18 14  57
3 2017-08-18 14:58:00 0.0601318 1.86596        2017 8 18 14  58
4 2017-08-18 14:59:00 0.0599276 1.83761        2017 8 18 14  59
5 2017-08-18 15:00:00 0.0598998 1.84177        2017 8 18 15   0

Мне пришлось использовать цикл for, чтобы уменьшить мою таблицу,Для этого я написал следующее:

datetime <- c()
eg_bf <-c ()

for(i in 1:8760){  
    hour= start + 3600

    DF= DF %>% 
      filter(datetime >= start & datetime < hour) %>% 
      summarise(eg= mean(pw))

    datetime= append(datetime, start)
    eg_bf= append(eg_bf, DF$eg)

    start= hour
    }
new_DF= data.frame(datetime, eg_bf)

Итак.Я смог получить свой новый набор данных со средним значением за каждый час года.

  datetime             eg_bf
1 2018-01-01 00:00:00  0.025
2 2018-01-01 01:00:00  0.003
3 2018-01-01 02:00:00  0.002
4 2018-01-01 03:00:00  0.010
5 2018-01-01 04:00:00  0.015

Проблема, с которой я сталкиваюсь, заключается в том, что это занимает много времени.Идея состоит в том, чтобы добавить этот расчет в блестящий пользовательский интерфейс, поэтому каждый раз, когда я делаю изменение, оно должно делать изменения быстрее.Есть идеи, как улучшить этот расчет?

Ответы [ 4 ]

0 голосов
/ 11 февраля 2019

Даже если вы нашли свой ответ, я думаю, что стоит упомянуть:

Если вы работаете с большим количеством данных, а скорость - это проблема, то вы можете не увидеть, сможете ли выиспользуйте data.table вместо dplyr

С помощью простого бенчмаркинга вы можете увидеть, насколько быстрее data.table:

library(dplyr)
library(lubridate)
library(data.table)
library(microbenchmark)
set.seed(123)

# dummy data, one year, one entry per minute
# first as data frame
DF <- data.frame(datetime = seq(as.POSIXct("2018-01-01 00:00:00"), 
                                as.POSIXct("2019-01-02 00:00:00"), 60),
                 pw = runif(527041)) %>% 
  mutate(year = year(datetime), m=month(datetime), 
         d=day(datetime), hour = hour(datetime))

# save it as a data.table
dt <- as.data.table(DF)

# transformation with dplyr
f_dplyr <- function(){
  DF %>% 
    group_by(year, m, d, hour) %>% 
    summarize(eg_bf = mean(pw))
}


# transformation with data.table
f_datatable <- function() {
  dt[, mean(pw), by=.(year, m, d, hour)]
}

# benchmarking
microbenchmark(f_dplyr(), f_datatable())

# 
# Unit: milliseconds
#          expr       min        lq     mean   median       uq      max neval cld
#     f_dplyr() 41.240235 44.075019 46.85497 45.64998 47.95968 76.73714   100   b
# f_datatable()  9.081295  9.712694 12.53998 10.55697 11.33933 41.85217   100  a

проверьте этот пост, он говорит о многом data.table vs dplyr: один может делать что-то хорошо, другой - плохо или плохо?

0 голосов
/ 11 февраля 2019

@ Ответ Адама Грюера предоставляет хорошее решение для переменной даты, которая должна решить ваш вопрос.Расчет среднего значения за час работает только с dplyr, хотя:

df %>%
  group_by(year, m, d, hr) %>%
  summarise(test = mean(pw))

# A tibble: 2 x 5
# Groups:   year, m, d [?]
   year     m     d    hr   test
  <int> <int> <int> <int>  <dbl>
1  2017     8    18    14 0.0609
2  2017     8    18    15 0.0599

Вы сказали в своем вопросе:

Когда я использую только эти функции, я могучтобы получить среднее значение за каждый час, но только за каждый месяц, и я хочу его за каждый день.

Что вы делали по-другому?

0 голосов
/ 11 февраля 2019

Как я понял, у вас есть фрейм данных 365 * 24 * 60 строк.Код ниже возвращает результат мгновенно.Результат - среднее значение (pw), сгруппированное по каждому часу года.


remove(list = ls())

library(dplyr)
library(lubridate)
library(purrr)
library(tibble)

date_time <- seq.POSIXt(
    as.POSIXct("2018-01-01"),
    as.POSIXct("2019-01-01"),
    by = "1 min"
)

n <- length(date_time)

data <- tibble(
    date_time = date_time,
    pw = runif(n),
    cu = runif(n),
    ye = year(date_time),
    mo = month(date_time),
    da = day(date_time),
    hr = hour(date_time)
)

grouped <- data %>% 
    group_by(
        ye, mo, da, hr
    ) %>% 
    summarise(
        mean_pw = mean(pw)
    )


0 голосов
/ 11 февраля 2019

вы можете попробовать это.используйте make_date из пакета lubridate, чтобы создать новый столбец date_time, используя столбцы year, month, day и hour вашего набора данных.Затем сгруппируйте и подведите итоги по новому столбцу

library(dplyr)
library(lubridate)
 df %>% 
   mutate(date_time = make_datetime(year, m, d, hr)) %>%  
   group_by(date_time) %>% 
   summarise(eg_bf = mean(pw))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...