First, let’s download daily climatic data for a specific location and store it in a dataframe.


library(easyclimate)
library(tidyr)
library(dplyr)

coords <- matrix(c(-5.36, 37.40), ncol = 2)

daily <- get_daily_climate(coords,
                           period = 2001:2005,
                           climatic_var = c("Prcp","Tmin","Tmax"))  

Here we calculate the daily mean temperature:


daily <- daily |> 
  mutate(Tmean = (Tmin + Tmax) / 2, #Daily mean temperature
         date = as.Date(date),
         month = format(date, format = "%m"),
         year = format(date, format = "%Y"))


Average climatic values per site or time period

To calculate average temperatures by site or time period we can use group_by and summarise from dplyr, or by and aggregate from base R:


daily |> 
  group_by(ID_coords) |> 
  summarise(Tmin.site = mean(Tmin),
            Tmean.site = mean(Tmean),
            Tmax.site = mean(Tmax))
## # A tibble: 1 × 4
##   ID_coords Tmin.site Tmean.site Tmax.site
##       <dbl>     <dbl>      <dbl>     <dbl>
## 1         1      11.9       18.4      24.9

daily |> 
  group_by(year) |>  
  summarise(Tmin.year = mean(Tmin),
            Tmean.year = mean(Tmean),
            Tmax.year = mean(Tmax)) |> 
  kable(digits = 1)
year Tmin.year Tmean.year Tmax.year
2001 12.2 18.5 24.8
2002 12.0 18.3 24.6
2003 12.5 18.7 24.9
2004 11.7 18.3 24.8
2005 11.3 18.3 25.3

daily |>  
  group_by(month) |> 
  summarise(Tmin.month = mean(Tmin),
            Tmean.month = mean(Tmean),
            Tmax.month = mean(Tmax)) |> 
  kable(digits = 1)
month Tmin.month Tmean.month Tmax.month
01 4.7 10.3 15.9
02 4.8 11.0 17.2
03 8.8 14.5 20.3
04 9.8 16.4 23.0
05 12.9 19.9 27.0
06 17.6 25.6 33.5
07 18.9 27.1 35.3
08 19.8 27.5 35.3
09 17.2 24.0 30.8
10 14.1 19.5 25.0
11 8.2 13.6 18.9
12 6.2 11.1 16.1

Similarly, you can calculate accumulated precipitation over different time periods:

daily |> 
  group_by(year) |>  
  summarise(sumPrec = sum(Prcp)) |> 
  kable(digits = 0)
year sumPrec
2001 568
2002 564
2003 643
2004 373
2005 261

daily |> 
  group_by(year, month) |> 
  summarise(sumPrec = sum(Prcp)) |>  
  pivot_wider(names_from = month, values_from = sumPrec) |> 
  kable(digits = 0)
year 01 02 03 04 05 06 07 08 09 10 11 12
2001 136 17 123 3 44 0 0 0 36 76 65 68
2002 31 9 101 53 14 3 0 0 80 32 141 100
2003 69 68 43 62 3 0 0 0 30 195 77 96
2004 10 80 63 40 61 0 0 2 2 70 9 37
2005 0 58 22 20 18 0 0 0 0 103 14 27


Climatic anomalies

Sometimes it can be useful to calculate the deviation of climate values from a reference value. For example, if we consider as the reference the mean value for the period 2001-2005, we can calculate the deviations per site and year as follows:


daily |>    
  group_by(ID_coords, year) |>  
  summarise(avgTm = mean(Tmean)) |>  
  group_by(ID_coords) |>  
  mutate(refTm = mean(avgTm)) |>  #Reference mean temperature
  mutate(devTm = avgTm - refTm) |>  
  kable(digits = 1)
ID_coords year avgTm refTm devTm
1 2001 18.5 18.4 0.1
1 2002 18.3 18.4 -0.1
1 2003 18.7 18.4 0.3
1 2004 18.3 18.4 -0.2
1 2005 18.3 18.4 -0.1

daily |>    
  group_by(ID_coords, year) |>  
  summarise(sumPrec = sum(Prcp)) |> 
  group_by(ID_coords) |> 
  mutate(refPrec = mean(sumPrec)) |>  #Reference precipitation
  mutate(devPrec =sumPrec - refPrec) |>  
  kable(digits = 0)
ID_coords year sumPrec refPrec devPrec
1 2001 568 482 86
1 2002 564 482 82
1 2003 643 482 161
1 2004 373 482 -109
1 2005 261 482 -221


Climatic events

Having daily values allows us to calculate climatic indices such as the number of consecutive days above a given temperature (e.g. heat waves or growing degree days), the number of spring frosts or the number of consecutive days without rain.


Let’s start with an example on heat waves, or number of days with maximum temperatures above a given threshold:


threshold <- 32  

daily |>  
  mutate(ID_coords = as.factor(ID_coords),
         year = factor(year)) |>  
  group_by(ID_coords, year) |>  
  mutate(event = ifelse(Tmax >= threshold, 1, 0), # NAs will be 0 
         start = c(1, diff(event) != 0),
         run = cumsum(start)) |>  
  filter(event == 1) |> 
  group_by(run, .add = TRUE) |>  
  mutate(length = n()) |>  
  group_by(ID_coords, year) |> 
  summarise(max_heatwave = max(length), # longest heatwave per year (in days)
            mean_heatwave = mean(length), # average length of heatwaves per year
            n_heatwave = n()) |>  # No. of events per year
  kable(digits = 1)
ID_coords year max_heatwave mean_heatwave n_heatwave
1 2001 28 14.6 94
1 2002 13 8.1 74
1 2003 31 14.3 97
1 2004 30 15.5 99
1 2005 27 15.0 93


To calculate the number of days with spring frosts (minimum temperatures below 0) we can use the next code:


spring.months <- c("03","04","05") # March to May

daily |>  
  mutate(ID_coords = as.factor(ID_coords),
         year = factor(year)) |>  
  filter(month %in% spring.months) |>  
  mutate(event = ifelse(Tmin < 0, 1, 0)) |>  # NAs will be 0 
  group_by(ID_coords, year) |>  
  mutate(n_frost = sum(event)) |>  # No. of days with minimum temperature < 0 per year
  filter(event == 1) |>  
  group_by(ID_coords, year, n_frost) |>  
  summarise(Tmin_frost_avg = mean(Tmin)/100) |>  # Mean minimum temperature of frost days
  ungroup() |>  
  complete(ID_coords, year, fill = list(n_frost = 0, Tmin_frost_avg = NA)) |>  
  kable()
ID_coords year n_frost Tmin_frost_avg
1 2001 0 NA
1 2002 0 NA
1 2003 0 NA
1 2004 1 -0.0050
1 2005 1 -0.0021


A dry periods can be defined as a specific number of consecutive days with no precipitation.


threshold <- 30 #threshold in days to count extreme long events of no-rain

daily %>%  
  mutate(event = ifelse(Prcp < 0.01, 1, 0), # NAs will be 0 
         start = c(1, diff(event) != 0)) |>  
    group_by(ID_coords, year) |>  
    mutate(run = cumsum(start)) |> 
    filter(event == 1) |>  
    group_by(ID_coords, year, run) |>  
    summarise(length = n()) |>  
    ungroup(run) |> 
    summarise(max_days_norain = max(length), # Maximum length of periods of consecutive days without rain per year
              mean_days_norain = mean(length), 
              nextreme_events = sum(length > threshold)) %>% # No. of events per year
  ungroup() |>  
  complete(ID_coords, year, 
           fill = list(max_days_norain = NA, mean_days_norain = NA, nevents = 0))  |>  
  kable(digits = 1)
ID_coords year max_days_norain mean_days_norain nextreme_events
1 2001 124 10.5 2
1 2002 102 9.9 1
1 2003 146 8.9 1
1 2004 87 12.0 2
1 2005 132 17.3 3


Using ClimInd in combination with easyclimate

The package climInd can be used to calculate multiple climatic indices from data obtained through easyclimate. For example:


Number of days with maximum temperature > 32ºC in summer (June-August):

library(ClimInd)

Tmax <- as.vector(daily$Tmax)
names(Tmax) <- as.character(format(daily$date, format = "%m/%d/%Y"))

d32(Tmax)
## 2001 2002 2003 2004 2005 
##   77   64   72   75   76


Growing degree days:

Tmean <- as.vector(daily$Tmean)
names(Tmean) <- as.character(format(daily$date, format = "%m/%d/%Y"))

gd4(data = Tmean, time.scale = "year") 
##     2001     2002     2003     2004     2005 
## 5304.165 5211.840 5371.645 5218.365 5234.140


Growing season length:

gsl(data = Tmean, time.scale = "year") 
## 2001 2002 2003 2004 2005 
##  365  365  365  366  365


Heavy precipitation days:

Prec <- as.vector(daily$Prcp)
names(Prec) <- as.character(format(daily$date, format = "%m/%d/%Y"))

d50mm(data = Prec, time.scale = "month")
##      Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 2001   0   0   0   0   0   0   0   0   0   0   0   0
## 2002   0   0   0   0   0   0   0   0   0   0   0   0
## 2003   0   0   0   0   0   0   0   0   0   0   0   0
## 2004   0   0   0   0   0   0   0   0   0   0   0   0
## 2005   0   0   0   0   0   0   0   0   0   0   0   0


Learn more

To learn more about downloading daily climatic data, please consult this vignette for point coordinates, or this other if you need to extract data for several polygons or a region.