Извлекать почасовые значения (и его индексы), превышающие среднемесячные значения в R

#r #dataframe #data.table

#r #dataframe #данные.таблица

Вопрос:

У меня есть два фрейма данных. df и df1. Оба файла данных большие (охватывают данные с 01-01-200 по 31-10-2019), поэтому я просто загрузил небольшой образец.

df содержит почасовые значения 3 переменных и соответствующий вектор даты, например:

            date           SH1          SH2         SH3        
     2000-01-01 00:00:00 1.941013e-01 1.506780e-01 0.124487891 
     2000-01-01 03:00:00 2.897915e-01 2.743722e-01 0.188432490 
     2000-01-01 06:00:00 3.139408e-01 2.250532e-01 0.001473900 
     2000-01-01 09:00:00 1.845777e-01 1.041934e-01 0.047391565 
     2000-01-01 12:00:00 1.022660e-01 6.179044e-02 0.008843402 
     

df <- structure(list(datex = structure(c(946681200, 946692000, 946702800, 
946713600, 946724400), class = c("POSIXct", "POSIXt")), SH1 = c(0.194101337780203, 
0.289791483274648, 0.313940773547535, 0.184577674010614, 0.102266008573448
), SH2 = c(0.150677966068861, 0.274372218123884, 0.225053245031368, 
0.104193416717294, 0.0617904375526934), SH3 = c(0.12448789070249, 
0.188432490298304, 0.00147390034529415, 0.0473915649486711, 0.00884340207176182
)), class = c("data.table", "data.frame"), row.names = c(NA, 
-5L))
  

В то время как df1 — это среднемесячное значение (за год) одних и тех же данных. Выглядит так:

       date       SH1       SH2       SH3       
  2000-01-01 0.7733497 0.6237698 0.4182768 
  2000-02-01 0.7308772 0.5575175 0.3636893  
  2000-03-01 0.3278784 0.3040463 0.2233942  
  2000-04-01 0.4496596 0.3124064 0.1805953  
  2000-05-01 0.4500503 0.4032727 0.2562054  

df1 <- structure(list(datex = structure(c(10957, 10988, 11017, 11048, 
11078), class = "Date"), SH1 = c(0.773349659462019, 0.730877175434939, 
0.327878366545974, 0.44965959591958, 0.450050258753037), SH2 = c(0.623769804010216, 
0.557517466419755, 0.304046348866025, 0.312406405495768, 0.403272666559865
), SH3 = c(0.418276825782115, 0.36368930844493, 0.223394192812674, 
0.18059530865458, 0.256205390604878)), row.names = c(NA, -5L), class = c("data.table", 
"data.frame"))
  

Я хочу извлечь значения в df, которые превышают соответствующее им среднемесячное значение (df1), а также получить местоположение (индекс) таких значений. Как я могу этого добиться? Я не эксперт в R, поэтому, пожалуйста, наберитесь терпения.

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

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

1. Помогло бы, если бы вы сделали эти примеры воспроизводимыми: вы могли бы использовать dput()

2. Я отредактировал вопрос и добавил результаты из dput()

3. Одна вещь data.table заключается в том, что вам нужно удалять часть .internal.selfref = ... . после каждого dput.

4. Также: в каком формате вы хотите получить результат?

5. отредактировано, я удалил internal.selfref-.. часть. Я не возражаю, если результатом будет фрейм данных или таблица данных, оба могут работать в этом случае.

Ответ №1:

Я бы сделал что-то таким образом:

 df %>% 
 group_by(year = year(date), month = month(date)) %>% 
  mutate(
    monthly_average_SH1 = mean(SH1),
    monthly_average_SH2 = mean(SH2),
    monthly_average_SH3 = mean(SH3),
    flag_exceed_SH1 = ifelse(SH1 > monthly_average_SH1, TRUE, FALSE),
    flag_exceed_SH2 = ifelse(SH2 > monthly_average_SH2, TRUE, FALSE),
    flag_exceed_SH3 = ifelse(SH3 > monthly_average_SH3, TRUE, FALSE),
    flag_any_exceed = ifelse(flag_exceed_SH1 | flag_exceed_SH2 | flag_exceed_SH3, TRUE, FALSE)
  ) %>% 
  filter(flag_any_exceed)
  

Это даст вам df со всеми строками, которые превысили значение. Обратите внимание, что df1 не был необходим, потому что вы можете сгенерировать средние значения в том же df.

Если вы хотите, чтобы индексы:

 df_2 <- df %>% 
  group_by(year = year(date), month = month(date)) %>% 
  mutate(
    monthly_average_SH1 = mean(SH1),
    monthly_average_SH2 = mean(SH2),
    monthly_average_SH3 = mean(SH3),
    flag_exceed_SH1 = ifelse(SH1 > monthly_average_SH1, TRUE, FALSE),
    flag_exceed_SH2 = ifelse(SH2 > monthly_average_SH2, TRUE, FALSE),
    flag_exceed_SH3 = ifelse(SH3 > monthly_average_SH3, TRUE, FALSE),
    flag_any_exceed = ifelse(flag_exceed_SH1 | flag_exceed_SH2 | flag_exceed_SH3, TRUE, FALSE)
  ) 
which(df2$flag_any_exceed)
  

Надеюсь, это полезно

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

1. Как я могу сделать это более эффективным способом, если у меня больше столбцов вместо 3?

2. я полагаю, вы могли бы использовать dplyr для разных функций.