Home > Software design >  Finding the 3 coldest consecutive months
Finding the 3 coldest consecutive months

Time:09-19

I am trying to write a code that finds the 3 consecutives months that are the coldest. For now I have written a code for the 3 first months (1,2,3) but then it should be applied to (4,5,6), (7,8,9), (10,11,12), (2,3,4), (5,6,7), (8,9,10), (11,12,1), (3,4,5), (6,7,8), (9,10,11) and (12,1,2) which are all the possible combinations of 3 consecutives months.

The code I wrote is here :

cold <- data_example %>%
  group_by(Site) %>%
  filter(Month %in% c(1,2,3)) %>%
  mutate(mean_temperature = mean(t_q)) %>%
  dplyr::select(-c(t_q,Month)) %>%
  distinct(Site, mean_temperature)

average_temp_month_1_2_3 <- cold$mean_temperature

Then I replaced the c(1,2,3) by all possiblities, I have created a new column for each output.

I end up with a dataset with row corresponding to Site and columns are all the possibilities of 3 consecutive months.

After I took the min value for each row using the function apply() and min() and it gives me the coldest quarter for each Site.

I am looking for a way to generalize it, like creating a loop on the possiblities.

The structure of data_example is as follow :

structure(list(Site = c(4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 13L, 
13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 
14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 15L, 15L, 15L, 
15L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 
17L, 17L, 17L, 17L, 17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 
18L, 18L, 18L, 18L, 18L, 18L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 
25L, 25L, 25L, 25L, 25L, 26L, 26L, 26L, 26L, 26L, 26L, 26L, 26L, 
26L, 26L, 26L, 26L), Month = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L), t_q = c(9.67754848470332, -6.74555496540183, 
5.67969761460384, 12.537207581471, -9.4899105618945, 21.0747672424502, 
15.2643039243614, -3.62839910494421, 11.3919028351455, 1.69988257436554, 
4.22015024307287, 11.7045830784212, 8.91437673833493, 0.579081429509138, 
-10.8207481229903, 7.05356868592628, 13.0911580912516, 17.2032089167605, 
-2.47642708849114, -11.2105599344486, 33.986736305027, 17.8578689773214, 
-14.9114468266335, 14.4681380389141, 0.568074240873411, 7.65458408777801, 
1.91368344556659, 6.01571556896127, 11.4858297513536, 2.2608458985328, 
-2.08200762781776, 12.1540989284163, 20.9941815285413, 0.375777604316208, 
-2.7137027317614, -6.17690210400591, 11.2549857164403, 17.447156776654, 
-6.96565197389579, -5.41542361226991, 11.1680111873065, 16.2266522778922, 
-11.4503938582433, 5.93300314835716, -18.2818398656237, 16.2930210946949, 
9.80219192652316, -0.48237356523527, 7.72680942503686, 5.84113084181759, 
9.66129413490096, -4.53018262186904, 7.42187509892118, 9.2559478576895, 
8.25120948667013, 8.18182063263247, 16.3703081943971, 19.5469951420341, 
3.71888263185773, -0.150179891749435, 1.32057298670562, -5.63556532224354, 
21.3918542474341, 4.58752188336035, 5.49430262894033, 5.99587512047837, 
-3.76459024109216, -8.53522098071824, 8.01805680562232, 26.2227490426066, 
8.90822434139878, 5.04259034084471, 6.89740304247746, 11.9484584922927, 
-11.5085102739471, 30.4526759119379, 21.878533782357, -5.39936677076962, 
-9.83965056853816, 19.3083455159472, 7.90653548036154, 3.11876660277767, 
-8.85027083180008, -9.9225496831988, 5.97307112581907, -2.83528336599284, 
-2.75758002814396, 4.68388181004449, 6.61649031537118, -6.65988084338133, 
-0.981075313384259, 5.84898952305179, -5.20962191660178, 0.416662319713158, 
-10.5336993269853, 19.5350642296553, 26.9696625385792, 15.3291059661081, 
15.0799591208354, 13.2310653499033, 7.2053382722482, -7.87288386491102, 
20.8083797469715, 6.16664220270041, 8.3360949793043, -14.4000921795463, 
-10.5503025782944, 14.3185205291177, 5.83802399796341, 2.49660818997943, 
15.7399297014092, -0.834086173817971, 12.4883230222372, 6.73548467376379, 
7.7988835803825, -5.13583355913738, 7.51054162811707, 11.6610602814336, 
-11.8864185954223, 4.2704440943851)), row.names = c(NA, -120L
), groups = structure(list(Site = c(4L, 5L, 13L, 14L, 15L, 16L, 
17L, 18L, 25L, 26L), .rows = structure(list(1:12, 13:24, 25:36, 
    37:48, 49:60, 61:72, 73:84, 85:96, 97:108, 109:120), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -10L), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

CodePudding user response:

You can use raster::movingFun to do a moving average with circular data, then use slice_min to get the minimum value per group.

library(dplyr)

circ <- function(x, by) ifelse(x%%by == 0, x, x%%by)
df %>% 
  group_by(Site) %>% 
  mutate(rolmean = raster::movingFun(t_q, n = 3, fun = mean, circular = TRUE)) %>% 
  slice_min(rolmean) %>% 
  mutate(coldest = toString(circ(c(Month-1, Month, Month 1), 12)))

output

# A tibble: 10 × 5
# Groups:   Site [10]
    Site Month     t_q rolmean coldest   
   <int> <int>   <dbl>   <dbl> <chr>     
 1     4     2  -6.75    2.87  1, 2, 3   
 2     5     3 -10.8    -1.06  2, 3, 4   
 3    13    11  -2.71   -2.84  10, 11, 12
 4    14     8   5.93   -7.93  7, 8, 9   
 5    15     3   9.66    3.66  2, 3, 4   
 6    16     7  -3.76   -2.10  6, 7, 8   
 7    17    11  -8.85   -5.22  10, 11, 12
 8    18    10   0.417  -5.11  9, 10, 11 
 9    25    10 -14.4    -5.54  9, 10, 11 
10    26    12   4.27   -0.593 11, 12, 1

CodePudding user response:

Using which.min in aggregate on a moving average window.

aggregate(t_q ~ Site, dat, \(s) {
  win <- 3  ## window length
  sq <- Map(seq, 1:(length(s) - win   1), win:length(s))
  toString(sq[[which.min(sapply(sq, \(sq) mean(s[sq])))]])
})
#    Site        t_q
# 1     4    1, 2, 3
# 2     5    2, 3, 4
# 3    13 10, 11, 12
# 4    14    7, 8, 9
# 5    15    2, 3, 4
# 6    16    6, 7, 8
# 7    17 10, 11, 12
# 8    18  9, 10, 11
# 9    25  9, 10, 11
# 10   26 10, 11, 12
  • Related