--- title: "Getting started with Rfactor" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with Rfactor} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` # Introduction `Rfactor` calculates rainfall erosivity from timestamped precipitation records. A typical workflow consists of: 1. reading and validating rainfall data; 2. identifying independent rainfall events; 3. calculating maximum rainfall intensities and rainfall kinetic energy; 4. calculating event EI30 erosivity; 5. classifying events according to configurable omission criteria; 6. aggregating contributing erosive-event EI30 by calendar month or year; 7. calculating multi-year mean monthly or annual rainfall erosivity from those period totals. The package focuses specifically on rainfall erosivity. It does not calculate the other USLE or RUSLE factors and does not perform spatial interpolation or mapping. ```{r load-package} library(Rfactor) ``` # Rainfall input `rf_read_rainfall()` expects a delimited file containing a timestamp column and a precipitation column. Precipitation values represent rainfall depth during each observation interval, in millimetres. The rainfall record does not need to contain every expected timestamp. Sparse records and temporal gaps are accepted when timestamp differences remain aligned with the declared base temporal resolution. For this vignette, create a small synthetic 1-minute rainfall record containing two rainfall events: - a 30-mm event in July; - a 3-mm low-intensity event in August. The long dry period between them is deliberately absent from the input file. ```{r create-example} event_1_time <- seq( from = as.POSIXct( "2025-07-01 12:00:00", tz = "UTC" ), by = "1 min", length.out = 30 ) event_2_time <- seq( from = as.POSIXct( "2025-08-01 12:00:00", tz = "UTC" ), by = "1 min", length.out = 30 ) example_rainfall <- data.frame( datetime = format( c( event_1_time, event_2_time ), "%Y-%m-%d %H:%M:%S", tz = "UTC" ), precip_mm = c( rep(1.0, 30), rep(0.1, 30) ) ) example_file <- tempfile( fileext = ".csv" ) utils::write.csv( example_rainfall, example_file, row.names = FALSE ) ``` Read the file through the public Rfactor reader: ```{r read-rainfall} rain <- rf_read_rainfall( example_file, datetime_col = "datetime", precip_col = "precip_mm", tz = "UTC", expected_interval_min = 1 ) head(rain) ``` `expected_interval_min = 1` declares that the underlying rainfall resolution is one minute. The approximately one-month gap between the two synthetic events is accepted because the package does not require a temporally complete rainfall series. The time zone should describe how the timestamps in the source data are to be interpreted. `"UTC"` is used here because the synthetic timestamps were created in UTC. # Calculation settings Calculation settings are created with `rf_settings()`. ```{r settings} settings <- rf_settings() settings ``` The principal defaults use: - a 6-hour rainfall-event break; - precipitation omission below 12.70 mm; - maximum 15-minute intensity omission below 25.40 mm/h; - `"all"` omission logic; - Brown and Foster (1987) rainfall kinetic energy. With `"all"` omission logic, an event is omitted only if all enabled omission conditions are satisfied. The comparisons are strict. For example, exactly 12.70 mm does not satisfy a criterion defined as precipitation less than 12.70 mm. # Identify rainfall events Independent rainfall events are identified with `rf_identify_storms()`. ```{r identify-events} storms <- rf_identify_storms( rain, settings = settings ) unique( storms$storm_id ) ``` With the default 6-hour break, consecutive positive-rainfall observations separated by 6 hours or less remain in the same event. A gap greater than 6 hours starts a new event. Any positive rainfall observation resets the storm-break clock in the fixed-interval algorithm validated against RIST 3.99.10. The object returned by `rf_identify_storms()` stores the calculation settings and temporal resolution as metadata, so the next calculation can normally use them automatically. # Calculate event EI30 Use `rf_calculate_ei30()` to calculate event precipitation, maximum rolling rainfall intensities, kinetic energy, EI30, and erosive-event classification. ```{r calculate-ei30} events <- rf_calculate_ei30( storms ) events[ , c( "storm_id", "event_start", "event_end", "duration_min", "precip_mm", "i15_mm_h", "i30_mm_h", "energy_mj_ha", "ei30", "omitted", "erosive" ) ] ``` Event EI30 is calculated as \[ EI_{30} = E \times I_{30}, \] where \(E\) is total rainfall kinetic energy in MJ/ha and \(I_{30}\) is the maximum continuous 30-minute rainfall intensity in mm/h. EI30 therefore has units of MJ mm/(ha h). The July event contains 30 mm of high-intensity rainfall and is retained as erosive under the default settings. The August event contains only 3 mm at low intensity. It satisfies both default omission conditions and is therefore classified as non-erosive. Notice that `ei30` is still calculated for the omitted event. The `erosive` classification determines whether that event contributes to period aggregation. # Aggregate rainfall erosivity Use `rf_calculate_rfactor()` to aggregate contributing event EI30 values by calendar month or year. ```{r monthly} monthly <- rf_calculate_rfactor( events, period = "monthly" ) monthly ``` Both July and August appear because both months contain identified rainfall events. August has `R = 0` and `n_events = 0` because its rainfall event is non-erosive. Months that are completely absent from the supplied event data are not created. Yearly aggregation uses the same principle: ```{r yearly} yearly <- rf_calculate_rfactor( events, period = "yearly" ) yearly ``` `n_events` is the number of erosive events with non-missing EI30 that actually contribute to the reported total. Because the example rainfall record contains observations from only one year, the resulting yearly value is a period total, not a multi-year mean R-factor. # Multi-year mean rainfall erosivity A yearly `R` value returned by `rf_calculate_rfactor()` is the sum of contributing event EI30 values calculated from the rainfall data available for that calendar year. It should not by itself be interpreted as the climatological long-term mean annual rainfall-runoff erosivity factor used by USLE or RUSLE. Once monthly or yearly R-factor values have been calculated for several years, `rf_calculate_mean_rfactor()` can be used to calculate their multi-year arithmetic mean. ## Mean annual rainfall erosivity For example, consider five yearly R-factor values: ```{r mean-annual-rfactor} yearly_multi_year <- data.frame( year = 2020:2024, R = c( 800, 900, NA, 700, 0 ) ) annual_mean <- rf_calculate_mean_rfactor( yearly_multi_year, period = "yearly" ) annual_mean ``` The missing value is excluded from the calculation, while the genuine zero is retained. The mean is therefore calculated from: ```text 800, 900, 700, 0 ``` and `n_years = 4`. A zero is valid information: it represents an available period with no contributing erosive events. An `NA` value instead represents an unavailable R-factor value and is not included in the mean. ## Multi-year monthly means For monthly input, a separate mean is calculated for each available calendar month. ```{r mean-monthly-rfactor} monthly_multi_year <- data.frame( year = c( 2020, 2021, 2022, 2020, 2021, 2022 ), month = c( 7, 7, 7, 8, 8, 8 ), R = c( 400, 500, 300, 0, NA, 20 ) ) monthly_mean <- rf_calculate_mean_rfactor( monthly_multi_year, period = "monthly" ) monthly_mean ``` July is calculated from three available yearly values. August is calculated from two available values because its missing value is excluded, while `R = 0` remains part of the calculation. The returned `n_years` column therefore reports the number of non-missing R-factor values actually used for each calendar month. Calendar months that are completely absent from the supplied table are not generated. ## Annual versus monthly means The mean annual R-factor is calculated directly from yearly R-factor values. It is not calculated by summing the twelve multi-year monthly means. Those two quantities need not be identical when different calendar months contain different numbers of available years. `rf_calculate_mean_rfactor()` also does not determine whether an available monthly or yearly R-factor value was derived from a complete rainfall record. Deriving a representative climatic R-factor therefore still requires an appropriate multi-year rainfall record together with an assessment of record completeness and representativeness. `Rfactor` deliberately leaves that assessment to the user. # Including all rainfall events The omission criteria can be disabled independently. To include every identified rainfall event: ```{r include-all} include_all <- rf_settings( omit_precip = FALSE, omit_intensity = FALSE ) all_storms <- rf_identify_storms( rain, settings = include_all ) all_events <- rf_calculate_ei30( all_storms ) all_events[ , c( "event_start", "precip_mm", "omitted", "erosive" ) ] ``` When both omission criteria are disabled, every identified rainfall event is retained. # Changing the kinetic-energy equation Three rainfall kinetic-energy equations are available: - `"brown_foster_1987"`; - `"mcgregor_1995"`; - `"laws_parsons_1943"`. For example: ```{r energy-equation} mcgregor_settings <- rf_settings( energy_equation = "mcgregor_1995" ) mcgregor_settings$energy_equation ``` The selected equation is subsequently used by `rf_calculate_ei30()` when calculating event kinetic energy. # Temporal resolution Requested rainfall-intensity durations must be compatible with the temporal resolution of the source rainfall data. Each requested duration must be an exact multiple of the observation interval. For example, 10-minute rainfall data can support 10-, 20-, 30-, and 60-minute rolling intensities: ```{r ten-minute-settings} settings_10min <- rf_settings( intensity_durations_min = c( 10, 20, 30, 60 ), omit_intensity_duration_min = 10 ) settings_10min ``` A true 5- or 15-minute intensity cannot be recovered directly from 10-minute rainfall totals. EI30 additionally requires an exact 30-minute intensity window. Consequently, the source interval must divide 30 minutes exactly. Fixed-interval Rfactor calculations have been empirically compared with RIST 3.99.10 using 1-, 5-, 10-, 15-, and 30-minute rainfall data. Temporal aggregation can change maximum rainfall intensity, kinetic energy, and EI30 even when the total precipitation amount is preserved. # Sparse rainfall records `rf_read_rainfall()` and `rf_validate_rainfall()` do not require every expected timestamp to be present. During rainfall-event identification, Rfactor reconstructs the expected regular time grid only from the first through the last positive-rainfall observation belonging to each event. Observations supplied by the user are preserved. Expected time positions absent from the supplied record are assigned zero recorded rainfall for the calculation. This inserted zero is a computational representation of an absent source position. It does not assert that the interval was observed and dry, and it does not estimate missing precipitation. Rfactor does not fill completely absent months or years and does not assess whether a rainfall record is climatologically complete. # Next steps The function help pages provide the complete argument and return-value documentation: ```r ?rf_settings ?rf_read_rainfall ?rf_identify_storms ?rf_calculate_ei30 ?rf_calculate_rfactor ?rf_calculate_mean_rfactor ``` A separate methodology and validation vignette documents the kinetic-energy equations, event-separation experiments, RIST comparisons, temporal-resolution validation, and interpretation of the resulting erosivity quantities in greater detail.