knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  warning = FALSE
)

library(nmecr)
library(ggplot2)
library(dplyr)

Normalized Metered Energy Consumption (NMEC)

Meter-based energy efficiency programs are proliferating across the globe. This proliferation is influenced by the widespread availability of high frequency energy use measurements from new metering technology as well as advancements in statistical regression and other empirical energy data modeling methodologies. Program administrators may report savings as the overall reduction in normalized metered energy consumption (NMEC). This method to determine savings is based on analysis of meter data collected prior to and after energy efficiency and conservation measures have been installed. Referred to as advanced measurement and verification (M&V) by the industry, this time-granular data and updated modeling methods provide several advantages over other methods used to quantify the benefits of energy efficiency:

The nmecr package streamlines the application of the NMEC approach by enabling the:

For an overview of nmcer, please refer nmecr_overview.pdf

Facilities outside the commercial sector have more drivers of energy use than just time and temperature. Institutional facilities, such as schools and government offices, have distinct operating profiles in different parts of the calendar year. These distinct operating profiles can be accounted for by adding variables to the dataframes that are served up to the modeling algorithms. These additional variables are indicator variables, indicating the beginning and end of an operating profile by switching between 1s and 0s.

Data

nmecr includes three datasets for this example: school_eload, school_temp, and school_op_mode. The data spans 1/1/2018 through 12/31/2018.

# Load data into an R session:

data(school_eload)
data(school_temp)
data(school_op_mode)

Baseline and Performance Period Dataframes for Modeling

create_dataframe() combines the eload and temp dataframes into one, filters by the specified start and end dates, and aggregates to an hourly, daily, or monthly data interval. It lines up all data such that each timestamp represents attributes up until that point, e.g. an eload value corresponding to 01/02/2018 represents the energy consumption up until then - the energy consumption of 01/01/2018. If additional variable data is supplied, this information is added to the dataframe created by create_dataframe(). The additional_variable_aggregation parameter handles how each of the additional variables is aggregated.

# Baseline Dataframe

baseline_df <- create_dataframe(eload_data = school_eload, 
                                temp_data = school_temp,
                                convert_to_data_interval = "Daily")

baseline_df_with_op_mode <- create_dataframe(
  eload_data = school_eload, 
  temp_data = school_temp,
  additional_independent_variables = school_op_mode,
  additional_variable_aggregation = c(median, median, median, median),
  convert_to_data_interval = "Daily"
  )
ggplot2::ggplot(baseline_df, aes(x = time, y = eload)) +
  geom_line() +
  xlab("Time") +
  scale_y_continuous(name = "Energy Consumption (kWh)", labels = scales::comma)+
  theme_minimal() +
  theme(legend.position = "bottom")

Figure 1: Baseline Energy Use over Time

ggplot2::ggplot(baseline_df, aes(x = temp, y = eload)) +
  geom_point() +
  xlab("Temperature") +
  scale_y_continuous(name = "Energy Consumption (kWh)", labels = scales::comma) +
  theme_minimal() +
  theme(legend.position = "bottom")

Figure 2: Baseline Energy Use over Temperature

As there isn't a high dependence on temperature, we expect that a model with Simple Linear Regression will not be able to capture all the variations in the energy use profile:

Model Creation

Time of Week and Temperature:

TOWT_model <- model_with_TOWT(training_data = baseline_df, 
                              model_input_options = 
                                assign_model_inputs(regression_type = "TOWT"))
TOWT_df <- TOWT_model$training_data

names(TOWT_df)[names(TOWT_df) == "model_fit"] <- "model_fit_without_op.mode_info"

TOWT_model_with_op_mode <- model_with_TOWT(training_data = baseline_df_with_op_mode, 
                            model_input_options = 
                              assign_model_inputs(regression_type = "TOWT"))

TOWT_df_with_op_mode <- TOWT_model_with_op_mode$training_data

names(TOWT_df_with_op_mode)[names(TOWT_df_with_op_mode) == "model_fit"] <- "model_fit_with_op.mode_info"

TOWT_all_data <- TOWT_df %>%
  dplyr::inner_join(TOWT_df_with_op_mode, by = c("time", "temp", "HDD", "CDD", "eload"))
TOWT_plot_data <- TOWT_all_data %>%
  tidyr::gather(key = "variable", value = "value", 
                -c("time", "temp", "CDD", "HDD", "school_holidays", 
                   "summer maintenance", "summer school", "pre-class ramp up"))

TOWT_plot_data %>%
    filter(variable != "model_fit_with_op.mode_info") %>%
  ggplot2::ggplot(aes(x = time, y = value, 
                      -c("time", "temp", "CDD", "HDD", "school_holidays", 
                         "summer maintenance", "summer school", "pre-class ramp up"))) +
  geom_line(aes(color = variable), size = 1) +
  xlab("Time") +
  scale_y_continuous(name = "Energy Data & Model Fit (kWh)", labels = scales::comma) +
  theme_minimal() +
  theme(legend.position = "bottom") +
  theme(legend.title = element_blank())

Figure 3: Baseline Energy Use modeled with Time-of-week and Temperature over Time

TOWT_plot_data %>%
    filter(variable != "model_fit_without_op.mode_info") %>%
  ggplot2::ggplot(aes(x = time, y = value, 
                      -c("time", "temp", "CDD", "HDD", "school_holidays", 
                         "summer maintenance", "summer school", "pre-class ramp up"))) +
  geom_line(aes(color = variable), size = 1) +
  xlab("Time") +
  scale_y_continuous(name = "Energy Data & Model Fit (kWh)", labels = scales::comma) +
  theme_minimal() +
  theme(legend.position = "bottom") +
  theme(legend.title = element_blank())

Figure 4: Baseline Energy Use modeled with Time-of-week and Temperature over Time with Operating Mode Information

 ggplot2::ggplot(TOWT_plot_data, aes(x = temp, y = value, 
                                     -c("time", "temp", "CDD", "HDD", "school_holidays", 
                                        "summer maintenance", "summer school", 
                                        "pre-class ramp up"))) +
  geom_point(aes(color = variable), size = 1) +
  xlab("Temperature") +
  scale_y_continuous(name = "Energy Data & Model Fit (kWh)", labels = scales::comma) +
  theme_minimal() +
  theme(legend.position = "bottom") +
  theme(legend.title = element_blank())

Figure 5: Baseline Energy Use modeled with Time-of-week and Temperature over Temperature

The plots show that the Time-of-Week and Temperature algorithm models the energy use profile better than SLR.

This insight can be confirmed through model statistics by using the calculate_summary_statistics() function. The following table summarizes the results from this function for each of the models assessed above:

TOWT_stats <- calculate_summary_statistics(TOWT_model)

TOWT_with_op_mode_stats <- calculate_summary_statistics(TOWT_model_with_op_mode)


all_stats <- bind_rows(TOWT_stats, TOWT_with_op_mode_stats)

model_names <- c("TOWT", "TOWT with op_mode")

all_stats <- bind_cols("Model Name" = model_names, all_stats)

all_stats

Assessing project fit for NMEC

Using the modeling statistics and the savings uncertainty for 10%, we can determine the validity of the NMEC approach for a certain project. For the building described here, the items that follow contain key values to be used for this assessment.

  1. CVRMSE: 17.8% (should be < 25%)
  2. NMBE: ~0.00% (should be < 0.5% and > -0.5%)

The California Public Utilities Commission requires savings to be detectable above model variations. nmecr interprets this using ASHRAE Guideline 14 - 2014's formulation for savings uncertainty, which relates the savings uncertainty to the model goodness of fit metric CV(RMSE), the confidence level, the amount of savings, the amount of data used to develop the model, and the amount of data required to report savings. It includes a correction when autocorrelation is present (which occurs mainly in models developed from daily and hourly data). LBNL has shown this uncertainty formulation with correction for autocorrelation underestimates the savings uncertainty. More work on this issue is needed. Until a better formulation is available, nmecr uses ASHRAE's method only as an estimation.

TOWT_savings <- calculate_savings_and_uncertainty(
  prediction_df = NULL, 
  savings_fraction = 0.1,
  modeled_object = TOWT_model_with_op_mode, 
  model_summary_statistics = TOWT_with_op_mode_stats,
  confidence_level = 90
  )

TOWT_savings$savings_summary_df
  1. Savings Uncertainty for 10% savings (at 90% confidence level): 22% (should be < 50%).

The savings percentage required to meet the threshold of 50% uncertainty, at the 90% confidence level, is 4.3% (as shown by the output above, see: savings_frac_for_50pct_uncertainty).

In addition to evaluating the model metrics, it is essential to ensure that the modeled profile follows the actual energy use closely (see Figure 5 above).



kW-Labs/nmecr documentation built on May 6, 2024, 9:28 p.m.