Фильтрация данных с более чем n повторениями путем определения среднего значения этих повторений

#r #dataframe #filter #dplyr

#r #фрейм данных #Фильтр #dplyr

Вопрос:

У меня есть данные временных рядов с интервалом в одну минуту (имя фрейма данных — pn.nano). Я хочу преобразовать его в усредненные данные за 5 минут. Но перед усреднением следует убедиться, что каждый 5-минутный интервал имеет не менее 3 значений (т. е. Каждый 5-минутный интервал должен содержать не менее 3 минут данных). Тогда следует выполнять только усреднение, иначе данные должны быть отфильтрованы.

Данные выглядят следующим образом. Имена столбцов (11.5, 15.4 и т.д.) — это загрязнители, изменение которых со временем отслеживается.

 nano.pn <- structure(list(datetime = structure(c(1491887640, 1491887700, 
           1491887760, 1491887820, 1491887880, 1491887940, 1491888000, 1491888060, 
           1491888120, 1491888180), tzone = "Asia/Calcutta", class = c("POSIXct", 
           "POSIXt")), `11.5` = c(5938.99, 5530.35, 4825.41, 4439.71, 4357.98, 
           4467.01, 3956.29, 3880.23, 3469.57, 3356.23), `15.4` = c(9594.94, 
           9124.55, 8382.42, 8223.1, 8216.26, 8454.1, 8112.84, 7519.49, 
           7060.94, 7337.3), `20.5` = c(5126.89, 4965.06, 4749.27, 4941.16, 
           5081.44, 5254.23, 5424.79, 4855.33, 4790.21, 5149.6), `27.4` = c(2936.92, 
           2882.55, 2704.88, 2856.22, 2868.12, 2909.07, 3106.77, 2887.35, 
           2802.64, 2853.24), `36.5` = c(1768.23, 1770.75, 1584.26, 1619.82, 
           1558.73, 1610.95, 1587.24, 1557.97, 1481.79, 1323.94)), row.names = c(NA, 
           -10L), class = c("tbl_df", "tbl", "data.frame"))
  

Мой подход заключается в использовании следующего кода:

 x <- nano.pn %>% mutate(datetime= floor_date(datetime, unit = "5 mins"))
n <- x %>% group_by(datetime) %>% summarise(countt= n())
n.pn.5min <- x %>% mutate(countt= rep(n$countt,n$countt)) %>% filter(countt>2) %>% 
                   group_by(datetime) %>% summarise_all(mean, na.rm= TRUE)
  

Хотя это работает нормально, есть ли какой-нибудь лучший подход?

Ответ №1:

Вы имеете в виду что-то вроде приведенного ниже?

 nano.pn %>%
  mutate(datetime = floor_date(datetime, unit = "5 mins")) %>%
  group_by(datetime) %>%
  filter(n() >= 3) %>%
  summarise_all(mean, na.rm = TRUE)
  

что дает

 # A tibble: 2 x 6
  datetime            `11.5` `15.4` `20.5` `27.4` `36.5`
  <dttm>               <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 2017-04-11 10:45:00  4724.  8480.  4998.  2844.  1629.
2 2017-04-11 10:50:00  3666.  7508.  5055.  2912.  1488.
  

Комментарии:

1. Я не знал, что n() можно использовать внутри самого filter() . Спасибо.

Ответ №2:

Работает ли это:

 > nano.pn %>% mutate(cuttime = cut(datetime, '5 mins')) %>% group_by(cuttime) %>% filter(n() > 3) %>% summarise(across(is.numeric, mean, na.rm = 1))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 2 x 6
  cuttime             `11.5` `15.4` `20.5` `27.4` `36.5`
  <fct>                <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 2017-04-11 10:44:00  5018.  8708.  4973.  2850.  1660.
2 2017-04-11 10:49:00  3826.  7697.  5095.  2912.  1512.
> 
  

Разница между моим результатом и результатом Томаса заключается в том, что, когда он использовал flood_date, первая строка в фрейме данных, у которой было время «10:44:00.000», изменилась на «10:40:00.000» и не была включена в среднее вычисление, поскольку это было единственное наблюдение в этой группе, а вторая строка во фрейме данных, у которой было время «10:44:00.000», изменилась на «10:40:00.000» и не была включена в среднее вычисление, поскольку это было единственное наблюдение в этой группе, и второев группе было 4 строки. У меня 5 в обеих группах. Поэтому, пожалуйста, используйте какой-либо код, который будет работать для вас.

Комментарии:

1. Спасибо, Картик, что указал на это. Ваш код заставил меня понять, что я должен использовать ceiling_date, а не floor_date. Но да, мне может понадобиться ваш тип кода тоже когда-нибудь в ближайшем будущем. У меня было еще одно сомнение, можете ли вы помочь. Если у меня есть другой набор данных с интервалом в 5 минут, и я хочу получить среднее значение этих данных в соответствии с временной шкалой второго набора данных, возможно ли это?

2. Конечно, вы имеете в виду одинаковые значения загрязняющих веществ, но в разные сроки?

3. Позвольте мне попробовать на примере. Допустим, у меня есть набор данных с независимой переменной «A» с интервалом в 1 минуту, и у меня есть набор данных с зависимой переменной «B» с интервалом в 5 минут. Я хочу получить среднее значение данных «A» за 5 минут, но на той же временной шкале, что и данные «B». Возможно ли это? Если я использую функцию типа left_join() , она выдаст только совпадающие значения обоих наборов данных, но не будет принимать среднее значение.

4. Поскольку они зависят, вы можете объединяться до тех пор, пока совпадает дата-время. т.е., Как указано выше, если данные в «A» сгруппированы в те же интервалы, что и «B», вы можете присоединиться.

5. Я думаю, что будет лучше опубликовать его с примером. Я сделаю это. Спасибо.