This tutorial covers how to run the FLEXvalue library in order to calculate avoided costs, GHG savings, and Total Resource Cost (TRC) and Program Administrator Cost (PAC) values for demand side measures, projects, or portfolios. This library uses a cleaned up version of the CPUC's electric an gas avoided costs, which have been reformatted into SQLite files.
Before calculating results, you must first download this SQLite file. It is currently being hosted publically at https://storage.googleapis.com/flexvalue-public-resources/{version}.db
. At the time of this writing, the most current avoided costs data available was compiled in 2020.
By default, this SQLite file will be saved in the flexvalue
. Since this notebook is stored in flexvalue/notebooks
, to maintain consistency we need to adjust the database location. You can do this through an environment variable.
import os
# to ensure this gets saved at flexvalue/db, since this notebook is executed in flexvalue/notebooks
try:
import google.colab
os.environ["DATABASE_LOCATION"] = '.'
except:
if not os.environ.get('DATABASE_LOCATION_ORIG'):
os.environ["DATABASE_LOCATION_ORIG"] = os.environ.get('DATABASE_LOCATION', '.')
os.environ["DATABASE_LOCATION"] = '../' + os.environ['DATABASE_LOCATION_ORIG']
# uncomment the line below if you are running on colab
#!pip install flexvalue --upgrade
You can download the SQLite file through a CLI command. By default, each time you run the command, it will download and overwrite the file for that version. However, there is a --skip-if-exists
parameter which will first check if that versions data has already been downloaded before attempting to download. The 2020 SQLite file is ~2 GB.
For the purposes of this tutorial, we will use the 2020 avoided costs data.
# This command can be run from the CLI. It will download the sqlite db that contains the avoided costs for electricity and gas and the deer load shape.
!flexvalue download-avoided-costs-data-db --skip-if-exists --version 2020
WARNING:root:This file already exists so it will not be downloaded again.
This database contains 3 tables: deer_ls
, avoided_costs_elec
, avoided_costs_gas
.
import pandas as pd
import sqlite3
db_filepath = os.path.join(os.environ['DATABASE_LOCATION'], "2020.db")
con = sqlite3.connect(db_filepath)
The DEER load shapes are normalized 8,760 hourly savings profiles that correspond to different end-use sectors and technologies (residential HVAC or commercial lighting for example). A full list is provided in reference . Annual deemed MWh savings values are typically assigned to a specific DEER load shape. The resulting 8,760 hourly savings values are then multiplied by the hourly electric avoided costs to produce the electric cost effectiveness benefits.
Additional ETL
Recurve has made a few changes to column names to incorporate residential and non-residential naming conventions but otherwise the format of the DEER load shapes does not need to be updated. Additional ETL is needed because the electric avoided costs begin on a day of the week that does not align with the DEER load shapes. Recurve has conducted extensive testing and has found that the DEER load shapes need to be shifted by -2 days in order to provide the best alignment with the CPUC’s existing Cost Effectiveness Tool.
Notes
There are different versions of the DEER load shape files for each of the four California IOUs. Currently, the raw database prefixes each DEER load shape name with the utility that it is associated with. This layout may change in future versions.
df_deer_load_shapes = pd.read_sql("select * from deer_load_shapes", con=con).drop("local_pkid_", axis=1)
df_deer_load_shapes
hour_of_year | PGE_RES_INDOOR_CFL_LTG | PGE_RES_REFGFRZR_HIGHEFF | PGE_RES_REFGFRZR_RECYC_CONDITIONED | PGE_RES_REFGFRZR_RECYC_UNCONDITIONED | PGE_RES_HVAC_EFF_AC | PGE_RES_HVAC_EFF_HP | PGE_RES_HVAC_DUCT_SEALING | PGE_RES_HVAC_REFRIG_CHARGE | PGE_RES_REFG_CHRG_DUCT_SEAL | ... | SCG_RES_REFGFRZR_RECYCLING | SCG_NONRES_INDOOR_CFL_LTG | SCG_NONRES_INDOOR_NON_CFL_LTG | SCG_NONRES_HVAC_CHILLERS | SCG_NONRES_HVAC_REFRIG_CHARGE | SCG_NONRES_HVAC_SPLIT_PACKAGE_AC | SCG_NONRES_HVAC_DUCT_SEALING | SCG_NONRES_HVAC_SPLIT_PACKAGE_HP | SCG_RES_CLOTHESDISHWASHER | SCG_RES_BLDGSHELL_INS | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0.000082 | 0.000082 | 0.000082 | 0.000065 | 0.000084 | 0.000343 | 0.000066 | 4.192640e-07 | 0.000056 | ... | 0.000080 | 0.000050 | 0.000028 | 0.000003 | -7.830000e-09 | 0.000007 | -5.500000e-06 | 0.000012 | 0.000068 | 0.000171 |
1 | 1 | 0.000051 | 0.000080 | 0.000080 | 0.000067 | 0.000088 | 0.000355 | 0.000076 | 2.076710e-07 | 0.000065 | ... | 0.000078 | 0.000049 | 0.000027 | 0.000002 | -9.740000e-09 | 0.000007 | 3.440000e-07 | 0.000013 | 0.000036 | 0.000183 |
2 | 2 | 0.000037 | 0.000078 | 0.000078 | 0.000068 | 0.000091 | 0.000359 | 0.000083 | 8.635210e-08 | 0.000072 | ... | 0.000075 | 0.000049 | 0.000027 | 0.000001 | -1.160000e-08 | 0.000008 | -1.120000e-06 | 0.000013 | 0.000020 | 0.000191 |
3 | 3 | 0.000033 | 0.000078 | 0.000078 | 0.000070 | 0.000093 | 0.000359 | 0.000088 | 1.557160e-08 | 0.000076 | ... | 0.000074 | 0.000049 | 0.000027 | 0.000001 | -1.320000e-08 | 0.000008 | -4.910000e-06 | 0.000015 | 0.000017 | 0.000195 |
4 | 4 | 0.000030 | 0.000078 | 0.000078 | 0.000070 | 0.000094 | 0.000359 | 0.000089 | 6.694710e-09 | 0.000076 | ... | 0.000073 | 0.000049 | 0.000031 | 0.000002 | -1.350000e-08 | 0.000010 | -4.940000e-06 | 0.000018 | 0.000028 | 0.000196 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
8755 | 8755 | 0.000232 | 0.000098 | 0.000098 | 0.000083 | 0.000028 | 0.000217 | 0.000023 | 3.968500e-06 | 0.000021 | ... | 0.000101 | 0.000098 | 0.000102 | 0.000022 | 2.740000e-05 | 0.000040 | 2.050000e-05 | 0.000067 | 0.000339 | 0.000073 |
8756 | 8756 | 0.000266 | 0.000095 | 0.000095 | 0.000077 | 0.000036 | 0.000244 | 0.000028 | 2.648030e-06 | 0.000024 | ... | 0.000096 | 0.000078 | 0.000070 | 0.000018 | 2.320000e-05 | 0.000029 | 1.010000e-05 | 0.000065 | 0.000329 | 0.000097 |
8757 | 8757 | 0.000245 | 0.000092 | 0.000092 | 0.000071 | 0.000048 | 0.000271 | 0.000035 | 1.697820e-06 | 0.000029 | ... | 0.000092 | 0.000070 | 0.000059 | 0.000012 | 6.880000e-06 | 0.000020 | 2.480000e-06 | 0.000067 | 0.000268 | 0.000122 |
8758 | 8758 | 0.000194 | 0.000088 | 0.000088 | 0.000067 | 0.000062 | 0.000298 | 0.000042 | 1.092550e-06 | 0.000036 | ... | 0.000087 | 0.000057 | 0.000036 | 0.000008 | 2.570000e-07 | 0.000013 | -1.400000e-06 | 0.000048 | 0.000191 | 0.000147 |
8759 | 8759 | 0.000131 | 0.000085 | 0.000085 | 0.000065 | 0.000075 | 0.000322 | 0.000053 | 7.241250e-07 | 0.000045 | ... | 0.000083 | 0.000056 | 0.000034 | 0.000005 | -2.290000e-09 | 0.000008 | -5.960000e-06 | 0.000015 | 0.000119 | 0.000169 |
8760 rows × 77 columns
deer_load_shapes_available = pd.read_sql(
"""
SELECT *
FROM deer_load_shapes
limit 1
""", con=con
)
list(deer_load_shapes_available.drop(['hour_of_year', 'local_pkid_'], axis=1).columns)
['PGE_RES_INDOOR_CFL_LTG', 'PGE_RES_REFGFRZR_HIGHEFF', 'PGE_RES_REFGFRZR_RECYC_CONDITIONED', 'PGE_RES_REFGFRZR_RECYC_UNCONDITIONED', 'PGE_RES_HVAC_EFF_AC', 'PGE_RES_HVAC_EFF_HP', 'PGE_RES_HVAC_DUCT_SEALING', 'PGE_RES_HVAC_REFRIG_CHARGE', 'PGE_RES_REFG_CHRG_DUCT_SEAL', 'PGE_RES_REFGFRZR_RECYCLING', 'PGE_NONRES_INDOOR_CFL_LTG', 'PGE_NONRES_INDOOR_NON_CFL_LTG', 'PGE_NONRES_HVAC_CHILLERS', 'PGE_NONRES_HVAC_REFRIG_CHARGE', 'PGE_NONRES_HVAC_SPLIT_PACKAGE_AC', 'PGE_NONRES_HVAC_DUCT_SEALING', 'PGE_NONRES_HVAC_SPLIT_PACKAGE_HP', 'PGE_RES_CLOTHESDISHWASHER', 'PGE_RES_BLDGSHELL_INS', 'SCE_RES_INDOOR_CFL_LTG', 'SCE_RES_REFGFRZR_HIGHEFF', 'SCE_RES_REFGFRZR_RECYC_CONDITIONED', 'SCE_RES_REFGFRZR_RECYC_UNCONDITIONED', 'SCE_RES_HVAC_EFF_AC', 'SCE_RES_HVAC_EFF_HP', 'SCE_RES_HVAC_DUCT_SEALING', 'SCE_RES_HVAC_REFRIG_CHARGE', 'SCE_RES_REFG_CHRG_DUCT_SEAL', 'SCE_RES_REFGFRZR_RECYCLING', 'SCE_NONRES_INDOOR_CFL_LTG', 'SCE_NONRES_INDOOR_NON_CFL_LTG', 'SCE_NONRES_HVAC_CHILLERS', 'SCE_NONRES_HVAC_REFRIG_CHARGE', 'SCE_NONRES_HVAC_SPLIT_PACKAGE_AC', 'SCE_NONRES_HVAC_DUCT_SEALING', 'SCE_NONRES_HVAC_SPLIT_PACKAGE_HP', 'SCE_RES_CLOTHESDISHWASHER', 'SCE_RES_BLDGSHELL_INS', 'SDGE_RES_INDOOR_CFL_LTG', 'SDGE_RES_REFGFRZR_HIGHEFF', 'SDGE_RES_REFGFRZR_RECYC_CONDITIONED', 'SDGE_RES_REFGFRZR_RECYC_UNCONDITIONED', 'SDGE_RES_HVAC_EFF_AC', 'SDGE_RES_HVAC_EFF_HP', 'SDGE_RES_HVAC_DUCT_SEALING', 'SDGE_RES_HVAC_REFRIG_CHARGE', 'SDGE_RES_REFG_CHRG_DUCT_SEAL', 'SDGE_RES_REFGFRZR_RECYCLING', 'SDGE_NONRES_INDOOR_CFL_LTG', 'SDGE_NONRES_INDOOR_NON_CFL_LTG', 'SDGE_NONRES_HVAC_CHILLERS', 'SDGE_NONRES_HVAC_REFRIG_CHARGE', 'SDGE_NONRES_HVAC_SPLIT_PACKAGE_AC', 'SDGE_NONRES_HVAC_DUCT_SEALING', 'SDGE_NONRES_HVAC_SPLIT_PACKAGE_HP', 'SDGE_RES_CLOTHESDISHWASHER', 'SDGE_RES_BLDGSHELL_INS', 'SCG_RES_INDOOR_CFL_LTG', 'SCG_RES_REFGFRZR_HIGHEFF', 'SCG_RES_REFGFRZR_RECYC_CONDITIONED', 'SCG_RES_REFGFRZR_RECYC_UNCONDITIONED', 'SCG_RES_HVAC_EFF_AC', 'SCG_RES_HVAC_EFF_HP', 'SCG_RES_HVAC_DUCT_SEALING', 'SCG_RES_HVAC_REFRIG_CHARGE', 'SCG_RES_REFG_CHRG_DUCT_SEAL', 'SCG_RES_REFGFRZR_RECYCLING', 'SCG_NONRES_INDOOR_CFL_LTG', 'SCG_NONRES_INDOOR_NON_CFL_LTG', 'SCG_NONRES_HVAC_CHILLERS', 'SCG_NONRES_HVAC_REFRIG_CHARGE', 'SCG_NONRES_HVAC_SPLIT_PACKAGE_AC', 'SCG_NONRES_HVAC_DUCT_SEALING', 'SCG_NONRES_HVAC_SPLIT_PACKAGE_HP', 'SCG_RES_CLOTHESDISHWASHER', 'SCG_RES_BLDGSHELL_INS']
There is a helper command if you want this list directly in python. Since the user_inputs file already has a field for utility, prefixing the DEER load shape with a utility name is not necessary. Therefore, this command returns the different options for you to provide in the user_inputs table.
from flexvalue import get_all_valid_deer_load_shapes
get_all_valid_deer_load_shapes(database_version='2020')
['RES_REFGFRZR_RECYCLING', 'RES_REFGFRZR_RECYC_CONDITIONED', 'RES_REFG_CHRG_DUCT_SEAL', 'NONRES_INDOOR_NON_CFL_LTG', 'NONRES_INDOOR_CFL_LTG', 'NONRES_HVAC_REFRIG_CHARGE', 'NONRES_HVAC_SPLIT_PACKAGE_AC', 'NONRES_HVAC_CHILLERS', 'RES_REFGFRZR_RECYC_UNCONDITIONED', 'RES_INDOOR_CFL_LTG', 'RES_BLDGSHELL_INS', 'RES_CLOTHESDISHWASHER', 'NONRES_HVAC_DUCT_SEALING', 'RES_HVAC_EFF_HP', 'RES_HVAC_REFRIG_CHARGE', 'NONRES_HVAC_SPLIT_PACKAGE_HP', 'RES_HVAC_EFF_AC', 'RES_REFGFRZR_HIGHEFF', 'RES_HVAC_DUCT_SEALING']
The electric avoided cost calculator compiles hourly marginal utility avoided costs for electric savings. Costs are provided for ten different components and are projected forward through approximately 2050. Avoided costs are distinct for each utility service territory (PG&E, SCE, SDG&E, and SoCalGas) and Climate Zone combination. The electric avoided cost calculator also contains hourly marginal greenhouse gas emissions data, which are also forecasted to approximately 2050.
The electric avoided cost calculator can be downloaded as a .xlsb file from here.
The electric avoided cost calculator is a macro-driven Excel file, so several ETL steps were done to combine all calculator results into a single table.
df_avoided_costs_electricity = pd.read_sql("select * from acc_electricity limit 5", con=con)
df_avoided_costs_electricity
utility | climate_zone | datetime | year | month | hour_of_day | hour_of_year | total | energy | losses | ... | capacity | transmission | distribution | cap_and_trade | ghg_adder | ghg_rebalancing | methane_leakage | marginal_ghg | ghg_adder_rebalancing | local_pkid_ | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | SCE | CZ14 | 2030-07-27 07:00:00 UTC | 2030 | 7 | 7 | 4975 | 119.059012 | 45.383113 | 3.285737 | ... | 0.0 | 0.00000 | 6.471175 | 31.413516 | 47.242566 | -24.250364 | 8.727548 | 0.251067 | 22.992202 | 08b41743a965111eb8a410242ac140002 |
1 | SCE | CZ14 | 2030-07-27 15:00:00 UTC | 2030 | 7 | 15 | 4983 | 286.330149 | 119.145551 | 8.626138 | ... | 0.0 | 0.00000 | 26.246724 | 54.512594 | 81.981105 | -24.250364 | 18.005627 | 0.517970 | 57.730741 | 18b41743a965111eb8a410242ac140002 |
2 | SCE | CZ14 | 2030-07-27 22:00:00 UTC | 2030 | 7 | 22 | 4990 | 121.740441 | 48.310949 | 3.497713 | ... | 0.0 | 0.00000 | 0.000143 | 33.465433 | 50.328428 | -24.250364 | 9.551730 | 0.274776 | 26.078064 | 28b41743a965111eb8a410242ac140002 |
3 | SCE | CZ14 | 2030-08-07 16:00:00 UTC | 2030 | 8 | 16 | 5248 | 1079.414557 | 112.717593 | 8.160754 | ... | 0.0 | 816.22002 | 19.504031 | 51.281444 | 77.121803 | -24.250364 | 16.707789 | 0.480635 | 52.871439 | 38b41743a965111eb8a410242ac140002 |
4 | SCE | CZ14 | 2030-09-02 12:00:00 UTC | 2030 | 9 | 12 | 5868 | 116.674556 | 44.841843 | 3.246549 | ... | 0.0 | 0.00000 | 0.000000 | 33.023035 | 49.663109 | -24.250364 | 9.374034 | 0.269664 | 25.412745 | 48b41743a965111eb8a410242ac140002 |
5 rows × 21 columns
The following are all of the unique utility/climate zone combinations available in the calculator
utility_climate_zone_combinations = pd.read_sql(
"""
SELECT utility, climate_zone
FROM acc_electricity
GROUP BY utility, climate_zone
ORDER BY utility, climate_zone
""", con=con
)
utility_climate_zone_combinations
utility | climate_zone | |
---|---|---|
0 | PGE | CZ1 |
1 | PGE | CZ11 |
2 | PGE | CZ12 |
3 | PGE | CZ13 |
4 | PGE | CZ16 |
5 | PGE | CZ2 |
6 | PGE | CZ3A |
7 | PGE | CZ3B |
8 | PGE | CZ4 |
9 | PGE | CZ5 |
10 | SCE | CZ10 |
11 | SCE | CZ13 |
12 | SCE | CZ14 |
13 | SCE | CZ15 |
14 | SCE | CZ16 |
15 | SCE | CZ6 |
16 | SCE | CZ8 |
17 | SCE | CZ9 |
18 | SDGE | CZ10 |
19 | SDGE | CZ14 |
20 | SDGE | CZ15 |
21 | SDGE | CZ7 |
There is a helper command if you want this list directly in python
from flexvalue import get_all_valid_utility_climate_zone_combinations
get_all_valid_utility_climate_zone_combinations(database_version='2020')
utility | climate_zone | |
---|---|---|
0 | PGE | CZ1 |
1 | PGE | CZ11 |
2 | PGE | CZ12 |
3 | PGE | CZ13 |
4 | PGE | CZ16 |
5 | PGE | CZ2 |
6 | PGE | CZ3A |
7 | PGE | CZ3B |
8 | PGE | CZ4 |
9 | PGE | CZ5 |
10 | SCE | CZ10 |
11 | SCE | CZ13 |
12 | SCE | CZ14 |
13 | SCE | CZ15 |
14 | SCE | CZ16 |
15 | SCE | CZ6 |
16 | SCE | CZ8 |
17 | SCE | CZ9 |
18 | SDGE | CZ10 |
19 | SDGE | CZ14 |
20 | SDGE | CZ15 |
21 | SDGE | CZ7 |
get_all_valid_utility_climate_zone_combinations(database_version='2020', utility='SDGE')
utility | climate_zone | |
---|---|---|
0 | SDGE | CZ10 |
1 | SDGE | CZ14 |
2 | SDGE | CZ15 |
3 | SDGE | CZ7 |
The gas avoided cost calculator compiles monthly marginal utility avoided costs for gas savings. Costs are provided for four different components and are projected forward through approximately 2050. Avoided costs are distinct for each utility service territory (PG&E, SCE, SDG&E, and SoCalGas). Avoided costs are also somewhat different for distinct end use categories.
The gas avoided cost calculator can be downloaded as a .xlsb file from here.
The gas avoided cost calculator is a macro-driven Excel file, so several ETL steps were done to combine all calculator results into a single table.
df_avoided_costs_gas = pd.read_sql("select * from acc_gas limit 10", con=con)
df_avoided_costs_gas
year | month | market | t_d | environment | upstream_methane | total | btm_methane | local_pkid_ | |
---|---|---|---|---|---|---|---|---|---|
0 | 2020 | 1 | 0.270297 | 0.338191 | 0.610998 | 0.022285 | 1.241770 | 0.015123 | 0b3cd36e0965211eb8a410242ac140002 |
1 | 2020 | 2 | 0.232967 | 0.338191 | 0.610998 | 0.022285 | 1.204440 | 0.015123 | 1b3cd36e0965211eb8a410242ac140002 |
2 | 2020 | 3 | 0.214088 | 0.338191 | 0.610998 | 0.022285 | 1.185562 | 0.015123 | 2b3cd36e0965211eb8a410242ac140002 |
3 | 2020 | 4 | 0.190713 | 0.000000 | 0.610998 | 0.022285 | 0.823995 | 0.015123 | 3b3cd36e0965211eb8a410242ac140002 |
4 | 2020 | 5 | 0.195206 | 0.000000 | 0.610998 | 0.022285 | 0.828489 | 0.015123 | 4b3cd36e0965211eb8a410242ac140002 |
5 | 2020 | 6 | 0.238072 | 0.000000 | 0.610998 | 0.022285 | 0.871354 | 0.015123 | 5b3cd36e0965211eb8a410242ac140002 |
6 | 2020 | 7 | 0.260448 | 0.000000 | 0.610998 | 0.022285 | 0.893731 | 0.015123 | 6b3cd36e0965211eb8a410242ac140002 |
7 | 2020 | 8 | 0.250158 | 0.000000 | 0.610998 | 0.022285 | 0.883440 | 0.015123 | 7b3cd36e0965211eb8a410242ac140002 |
8 | 2020 | 9 | 0.238864 | 0.000000 | 0.610998 | 0.022285 | 0.872147 | 0.015123 | 8b3cd36e0965211eb8a410242ac140002 |
9 | 2020 | 10 | 0.261744 | 0.000000 | 0.610998 | 0.022285 | 0.895026 | 0.015123 | 9b3cd36e0965211eb8a410242ac140002 |
user_inputs_file: A file that is one row per meter that contains all of the parameters necessary to calculate avoided costs for that meter. The load_shape column in this table corresponds either with a DEER load shape or a column name in the metered_load_shape_file.
*NOTE: If using the user_inputs in python, the code expects it to be indexed on ID
.
metered_load_shape_file: A file that is one row per hour of year, with each column being a unique identifier.
NOTE: If using the metered_load_shape in python, the code expects it to be indexed on hour_of_year
.
For the purposes of testing, we provide some example files that can be used. They can be created into CSVs for CLI command usage using a special CLI command. In this case, the files will be saved to the flexvalue/test_data
folder.
flexvalue generate-example-inputs
The inputs can also be directly called in python using the following code.
from flexvalue.examples import get_example_user_inputs_deer, get_example_user_inputs_metered, get_example_metered_load_shape
user_inputs_deer = get_example_user_inputs_deer()
user_inputs_metered = get_example_user_inputs_metered()
metered_load_shape = get_example_metered_load_shape()
!flexvalue generate-example-inputs --output-filepath ../test_data
os.listdir('../test_data')
['example_user_inputs_deer.csv', 'example_user_inputs_metered.csv', 'example_metered_load_shape.csv']
from flexvalue.examples import get_example_user_inputs_deer, get_example_user_inputs_metered, get_example_metered_load_shape
metered_load_shape = pd.read_csv('../test_data/example_metered_load_shape.csv', index_col='hour_of_year')
# or
metered_load_shape = get_example_metered_load_shape()
user_inputs_deer = pd.read_csv('../test_data/example_user_inputs_deer.csv')
# or
user_inputs_deer = get_example_user_inputs_deer(database_version='2020')
user_inputs_metered = pd.read_csv('../test_data/example_user_inputs_metered.csv')
# or
user_inputs_metered = get_example_user_inputs_metered(metered_load_shape.columns)
pd.concat([user_inputs_metered, user_inputs_deer])
load_shape | start_year | start_quarter | utility | climate_zone | units | eul | ntg | discount_rate | admin | measure | incentive | therms_profile | therms_savings | mwh_savings | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ID | |||||||||||||||
heat_pump_impact1 | heat_pump_impact1 | 2021 | 1 | PGE | CZ12 | 1 | 15 | 1.00 | 0.0766 | 100 | 2000 | 1000 | winter | 400 | 1 |
deer_id_0 | RES_REFGFRZR_RECYCLING | 2020 | 1 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 10000 | 2000 | 3000 | annual | 100 | 1000 |
deer_id_1 | RES_REFGFRZR_RECYC_CONDITIONED | 2020 | 2 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 20000 | 4000 | 6000 | annual | 200 | 2000 |
deer_id_2 | RES_REFG_CHRG_DUCT_SEAL | 2020 | 3 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 30000 | 6000 | 9000 | annual | 300 | 3000 |
deer_id_3 | NONRES_INDOOR_NON_CFL_LTG | 2020 | 4 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 40000 | 8000 | 12000 | annual | 400 | 4000 |
deer_id_4 | NONRES_INDOOR_CFL_LTG | 2020 | 1 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 50000 | 10000 | 15000 | annual | 500 | 5000 |
metered_load_shape
file or an available DEER load shape)Note: Because the DEER load shapes are normalized, if a DEER load shape is used the mwh_savings
entry should be the annual electricity savings for that element. If a metered or custom load shape is used, the mwh_savings
should be set to the annual electricity savings if the load shape is normalized or set to 1 if the load shape has the intended absolute savings values.
There are two ways to run this library: 1) through the CLI, 2) using a python object.
The cli command to run if only DEER load shapes are being used is:
flexvalue get-results --user-inputs-filepath {user_inputs_filepath}
The cli command to run if you also want to supply metered load shapes:
flexvalue get-results --user-inputs-filepath {user_inputs_filepath} --metered-load-shape-filepath {metered_load_shape_filepath}
By default, the CLI command generates an HTML report containing many key plots. Use the flexvalue get-results --help
command to get descriptions for the different inputs.
!flexvalue get-results --help
!flexvalue get-results --user-inputs-filepath ../test_data/example_user_inputs_deer.csv --report-filepath reports/example_report_deer.html
!flexvalue get-results \
--user-inputs-filepath ../test_data/example_user_inputs_metered.csv \
--metered-load-shape-filepath ../test_data/example_metered_load_shape.csv \
--report-filepath reports/example_report_metered.html
If using this library in python, you should know about the a key class that all code execution is built from.
The primary class is called FlexValueRun
. This represents a single "run" of the flexvlaue library. To initialize this object, you need to pass in a database_version
parameter, which indicates which version to use. This field is simply looking for a sqlite file in flexvalue/db/{version}.db
.
You also can pass a metered_load_shape dataframe, indexed on hour_of_year
. If you are only looking for DEER results, you don't need to pass this parameter.
from flexvalue import FlexValueRun
user_inputs_deer
load_shape | start_year | start_quarter | utility | climate_zone | units | eul | ntg | discount_rate | admin | measure | incentive | therms_profile | therms_savings | mwh_savings | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ID | |||||||||||||||
deer_id_0 | RES_REFGFRZR_RECYCLING | 2020 | 1 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 10000 | 2000 | 3000 | annual | 100 | 1000 |
deer_id_1 | RES_REFGFRZR_RECYC_CONDITIONED | 2020 | 2 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 20000 | 4000 | 6000 | annual | 200 | 2000 |
deer_id_2 | RES_REFG_CHRG_DUCT_SEAL | 2020 | 3 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 30000 | 6000 | 9000 | annual | 300 | 3000 |
deer_id_3 | NONRES_INDOOR_NON_CFL_LTG | 2020 | 4 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 40000 | 8000 | 12000 | annual | 400 | 4000 |
deer_id_4 | NONRES_INDOOR_CFL_LTG | 2020 | 1 | PGE | CZ3A | 1 | 9 | 0.95 | 0.0766 | 50000 | 10000 | 15000 | annual | 500 | 5000 |
# Running with the ids that are associated with DEER load shapes
from flexvalue.examples import get_example_user_inputs_deer
flx_run = FlexValueRun(database_version='2020')
user_inputs_deer = get_example_user_inputs_deer(database_version='2020')
outputs_table_deer, outputs_table_totals_deer, electric_benefits_deer, gas_benefits_deer = flx_run.get_results(user_inputs=user_inputs_deer)
outputs_table_deer
ID | load_shape | start_year | start_quarter | utility | climate_zone | units | eul | ntg | discount_rate | ... | TRC (and PAC) Total Benefits ($) | TRC Costs ($) | PAC Costs ($) | Electricity First Year Net Savings (MWh) | Electricity Lifecycle Net Savings (MWh) | Gas First Year Net Savings (Therms) | Gas Lifecycle Net Savings (Therms) | Electricity Lifecycle GHG Savings (Tons) | Gas Lifecycle GHG Savings (Tons) | Total Lifecycle GHG Savings (Tons) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | deer_id_0 | RES_REFGFRZR_RECYCLING | 2020 | 1 | PGE | CZ3A | 1.0 | 9 | 0.95 | 0.0766 | ... | 711520.05 | 12011.48 | 12943.63 | 950.017 | 8550.152 | 95.0 | 855.0 | 2329.184 | 5.13 | 2334.314 |
1 | deer_id_1 | RES_REFGFRZR_RECYC_CONDITIONED | 2020 | 2 | PGE | CZ3A | 1.0 | 9 | 0.95 | 0.0766 | ... | 1450840.63 | 24022.96 | 25887.26 | 1900.007 | 17100.059 | 190.0 | 1710.0 | 4710.446 | 10.26 | 4720.706 |
2 | deer_id_2 | RES_REFG_CHRG_DUCT_SEAL | 2020 | 3 | PGE | CZ3A | 1.0 | 9 | 0.95 | 0.0766 | ... | 2688485.24 | 36034.44 | 38830.89 | 2849.902 | 25649.122 | 285.0 | 2565.0 | 7508.371 | 15.39 | 7523.761 |
3 | deer_id_3 | NONRES_INDOOR_NON_CFL_LTG | 2020 | 4 | PGE | CZ3A | 1.0 | 9 | 0.95 | 0.0766 | ... | 2630599.95 | 48045.92 | 51774.52 | 3800.006 | 34200.052 | 380.0 | 3420.0 | 9007.701 | 20.52 | 9028.221 |
4 | deer_id_4 | NONRES_INDOOR_CFL_LTG | 2020 | 1 | PGE | CZ3A | 1.0 | 9 | 0.95 | 0.0766 | ... | 3227165.03 | 60057.40 | 64718.15 | 4750.008 | 42750.068 | 475.0 | 4275.0 | 11130.332 | 25.65 | 11155.982 |
5 rows × 30 columns
# Running with the ids that are associated with metered load shapes
from flexvalue.examples import get_example_user_inputs_metered, get_example_metered_load_shape
metered_load_shape = get_example_metered_load_shape()
flx_run = FlexValueRun(database_version='2020', metered_load_shape=metered_load_shape)
user_inputs_metered = get_example_user_inputs_metered(metered_load_shape.columns)
outputs_table_metered, outputs_table_totals_metered, electric_benefits_metered, gas_benefits_metered = flx_run.get_results(user_inputs=user_inputs_metered)
outputs_table_metered
ID | load_shape | start_year | start_quarter | utility | climate_zone | units | eul | ntg | discount_rate | ... | TRC (and PAC) Total Benefits ($) | TRC Costs ($) | PAC Costs ($) | Electricity First Year Net Savings (MWh) | Electricity Lifecycle Net Savings (MWh) | Gas First Year Net Savings (Therms) | Gas Lifecycle Net Savings (Therms) | Electricity Lifecycle GHG Savings (Tons) | Gas Lifecycle GHG Savings (Tons) | Total Lifecycle GHG Savings (Tons) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | heat_pump_impact1 | heat_pump_impact1 | 2021 | 1 | PGE | CZ12 | 1.0 | 15 | 1.0 | 0.0766 | ... | 5084.78 | 2062.42 | 1081.21 | -0.932 | -13.984 | 400.0 | 6000.0 | -4.935 | 36.0 | 31.065 |
1 rows × 30 columns
If you use the CLI command, an HTML report will be generated unless you use the --exclude-report
parameter. In python, you can generate the plots that go into that report using the plot_results(..)
function.
from flexvalue.plots import plot_results
plot_results(outputs_table_totals_metered, electric_benefits_metered, gas_benefits_metered)