This chapter explains how to calculate Chilling Hours using R and the chillR package. Chilling Hours measure the number of hours where temperatures are between 0°C and 7.2°C, which is important for certain plants to meet their cold requirements during dormancy and grow properly.
The calculation requires hourly temperature data, which is not always available. The chillR package provides tools to approximate data from daily records. In this example, the dataset Winters_hours_gaps is used, containing hourly temperature data recorded in 2008 from a walnut orchard in Winters, California.
The chillR package is loaded using library(chillR). The relevant columns (year, month, day, hour, temperature) are extracted and stored in a new dataset named hourtemps, ensuring the correct format for calculating Chilling Hours.
hourtemps <- Winters_hours_gaps[,c("Year",
"Month",
"Day",
"Hour",
"Temp")]
Chilling Hours are defined as any hour where the temperature falls between 0°C and 7.2°C. In R, this is implemented using a logical condition:
hourtemps[, "Chilling_Hour"] <- hourtemps$Temp >= 0 & hourtemps$Temp <= 7.2
A new column Chilling_Hour (TRUE/FALSE) is created to indicate whether a given hour qualifies. The total number of Chilling Hours can then be calculated using sum(hourtemps$Chilling_Hour).
To simplify the process, a function CH() was created to automatically add the Chilling_Hour column:
CH <- function(hourtemps) {
hourtemps[, "Chilling_Hour"] <- hourtemps$Temp >= 0 & hourtemps$Temp <= 7.2
return(hourtemps)
}
Additionally, a function sum_CH() was developed to calculate the total number of Chilling Hours between two specific dates:
sum_CH <- function(hourtemps, Start_Year, Start_Month, Start_Day, Start_Hour,
End_Year, End_Month, End_Day, End_Hour) {
hourtemps[,"Chilling_Hour"] <- hourtemps$Temp >= 0 & hourtemps$Temp <= 7.2
Start_Index <- which(hourtemps$Year == Start_Year & hourtemps$Month == Start_Month &
hourtemps$Day == Start_Day & hourtemps$Hour == Start_Hour)
End_Index <- which(hourtemps$Year == End_Year & hourtemps$Month == End_Month &
hourtemps$Day == End_Day & hourtemps$Hour == End_Hour)
CHs <- sum(hourtemps$Chilling_Hour[Start_Index:End_Index])
return(CHs)
}
This function uses the which() function to identify the relevant rows in the dataset based on the selected time range.
Instead of passing year, month, day, and hour separately, compact strings in the format YEARMODAHO (e.g., 2008040100 for April 1, 2008, at 00:00) can be used. The function extracts values using substr() and converts them into numeric values.
sum_CH <- function(hourtemps, startYEARMODAHO, endYEARMODAHO) {
hourtemps[, "Chilling_Hour"] <- hourtemps$Temp >= 0 & hourtemps$Temp <= 7.2
startYear <- as.numeric(substr(startYEARMODAHO, 1, 4))
startMonth <- as.numeric(substr(startYEARMODAHO, 5, 6))
startDay <- as.numeric(substr(startYEARMODAHO, 7, 8))
startHour <- as.numeric(substr(startYEARMODAHO, 9, 10))
endYear <- as.numeric(substr(endYEARMODAHO, 1, 4))
endMonth <- as.numeric(substr(endYEARMODAHO, 5, 6))
endDay <- as.numeric(substr(endYEARMODAHO, 7, 8))
endHour <- as.numeric(substr(endYEARMODAHO, 9, 10))
Start_Index <- which(hourtemps$Year == startYear & hourtemps$Month == startMonth &
hourtemps$Day == startDay & hourtemps$Hour == startHour)
End_Index <- which(hourtemps$Year == endYear & hourtemps$Month == endMonth &
hourtemps$Day == endDay & hourtemps$Hour == endHour)
CHs <- sum(hourtemps$Chilling_Hour[Start_Index:End_Index])
return(CHs)
}
Using the function sum_CH(), it was calculated that between April 1st and October 11th, 2008, the walnut orchard experienced 77 Chilling Hours:
sum_CH(hourtemps, startYEARMODAHO = 2008040100, endYEARMODAHO = 2008101100)
[1] 77
Exercises on basic chill modelingWH <- function(data)
{data[, "Warm_Hour"] <- data$Temp > 25
return(data)
}
Winters_hours_gaps dataset.WH(Winters_hours_gaps)
| Year | Month | Day | Hour | Temp_gaps | Temp | Warm_Hour |
|---|---|---|---|---|---|---|
| 2008 | 3 | 3 | 10 | 15.127 | 15.127 | FALSE |
| 2008 | 3 | 3 | 11 | 17.153 | 17.153 | FALSE |
| 2008 | 3 | 3 | 12 | 18.699 | 18.699 | FALSE |
| 2008 | 3 | 3 | 13 | 18.699 | 18.699 | FALSE |
| 2008 | 3 | 3 | 14 | 18.842 | 18.842 | FALSE |
| 2008 | 3 | 3 | 15 | 19.508 | 19.508 | FALSE |
| 2008 | 3 | 3 | 16 | 19.318 | 19.318 | FALSE |
| 2008 | 3 | 3 | 17 | 17.701 | 17.701 | FALSE |
| 2008 | 3 | 3 | 18 | 15.414 | 15.414 | FALSE |
| 2008 | 3 | 3 | 19 | 12.727 | 12.727 | FALSE |
sum_WH <- function(data,
startYEARMODAHO,
endYEARMODAHO)
{data[,"Warm_Hour"] <- data$Temp > 25
startYear <- as.numeric(substr(startYEARMODAHO, 1, 4))
startMonth <- as.numeric(substr(startYEARMODAHO, 5, 6))
startDay <- as.numeric(substr(startYEARMODAHO, 7, 8))
startHour <- as.numeric(substr(startYEARMODAHO, 9, 10))
endYear <- as.numeric(substr(endYEARMODAHO, 1, 4))
endMonth <- as.numeric(substr(endYEARMODAHO, 5, 6))
endDay <- as.numeric(substr(endYEARMODAHO, 7, 8))
endHour <- as.numeric(substr(endYEARMODAHO, 9, 10))
Start_Date <- which(data$Year == startYear &
data$Month == startMonth &
data$Day == startDay &
data$Hour == startHour)
End_Date <- which(data$Year == endYear &
data$Month == endMonth &
data$Day == endDay &
data$Hour == endHour)
WHs <- sum(data$Warm_Hour[Start_Date:End_Date])
return(WHs)
}
Application Example:
sum_WH(Winters_hours_gaps, startYEARMODAHO = 2008080100,
endYEARMODAHO = 2008083100)
[1] 283
During the month of August 2008, from the 1st to the 31st, the walnut orchard experienced a total of 283 warm hours (defined as hours when the temperature exceeded 25°C).