In [181]:
import pickle
from collections import namedtuple
import pandas as pd
import numpy as np
from importlib import reload
import sys
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.dates as mdates
import datetime

# bench_util module is in the parent directory, because it will be part of
# the production code.  Add the parent directory to the Path so Python can
# import from there
sys.path.insert(0, '../')   
import bench_util as bu
import graph_util as gu

Unpickle the Dataframe for Preprocessed Utility Data & Make Utility Function Object


In [182]:
# Unpickle the pre-processed DataFrame
df = pickle.load(open('dfu3.pkl', 'rb'))

# Unpickle the raw utility bill DataFrame, which is needed below to make
# the utility function object.
df_raw = pickle.load(open('df_raw.pkl', 'rb'))

df.head()  # the processed data


Out[182]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
0 03 Electricity 2005 12 Electricity charge kWh 1904.657880 49.5 14790.748577 2006 6 50.466034
1 03 Electricity 2006 1 Electricity charge kWh 5430.493797 93.0 42665.790911 2006 7 145.575679
2 03 Electricity 2006 2 Electricity charge kWh 5764.406730 84.0 45010.439348 2006 8 153.575619
3 03 Electricity 2006 3 Electricity charge kWh 6349.255299 93.0 46311.547557 2006 9 158.015000
4 03 Electricity 2006 4 Electricity charge kWh 5529.385224 90.0 40392.812893 2006 10 137.820278

In [183]:
# this is only needed to update any code changes I may have made
# since last importing the module above.
reload(bu) 
reload(gu)

# Make an object that has the various utility functions.
# The object needs access to the raw utility bill DataFrame and the spreadsheet
# containing other application data.
ut = bu.Util(df_raw, '../data/Other_Building_Data.xlsx')

In [184]:
# Testing site.  Final code will loop through all sites
site = 'ANSBG1'

In [185]:
template_data = {}

Energy Use Overview Report - Page 4


In [186]:
# From the main DataFrame, get only the rows for this site, and only get
# the needed columns for this analysis
usage_df1 = df.query('site_id == @site')[['service_type', 'fiscal_year', 'fiscal_mo', 'mmbtu']]
usage_df1.head()


Out[186]:
service_type fiscal_year fiscal_mo mmbtu
30353 Electricity 2006 12 24.71994
30354 Electricity 2006 12 0.00000
30355 Electricity 2006 12 NaN
30356 Electricity 2007 1 47.29032
30357 Electricity 2007 1 0.00000

In [187]:
usage_df2 = pd.pivot_table(
    usage_df1, 
    values='mmbtu', 
    index=['fiscal_year'], 
    columns=['service_type'],
    aggfunc=np.sum
)

usage_df2 = usage_df2.drop(labels=['Sewer', 'Water'], axis=1)

usage_df2


Out[187]:
service_type Electricity Natural Gas Oil #1
fiscal_year
2006 24.719940 NaN NaN
2007 630.537600 NaN NaN
2008 708.924675 NaN NaN
2009 656.786639 4472.297100 264.465
2010 641.697942 4416.021590 NaN
2011 664.086865 5203.093510 NaN
2012 683.037908 4183.582316 NaN
2013 600.549539 3545.521645 NaN
2014 616.351563 2163.879000 NaN
2015 664.534768 2082.877839 NaN
2016 595.196414 2151.683625 NaN
2017 880.345629 2112.299698 NaN
2018 113.573073 186.531677 NaN

In [188]:
# Add in columns for the missing services
missing_services = bu.missing_energy_services(usage_df2.columns)
bu.add_columns(usage_df2, missing_services)
usage_df2


Out[188]:
service_type Electricity Natural Gas Oil #1 Steam
fiscal_year
2006 24.719940 NaN NaN 0.0
2007 630.537600 NaN NaN 0.0
2008 708.924675 NaN NaN 0.0
2009 656.786639 4472.297100 264.465 0.0
2010 641.697942 4416.021590 NaN 0.0
2011 664.086865 5203.093510 NaN 0.0
2012 683.037908 4183.582316 NaN 0.0
2013 600.549539 3545.521645 NaN 0.0
2014 616.351563 2163.879000 NaN 0.0
2015 664.534768 2082.877839 NaN 0.0
2016 595.196414 2151.683625 NaN 0.0
2017 880.345629 2112.299698 NaN 0.0
2018 113.573073 186.531677 NaN 0.0

In [189]:
# Add a Total column that sums the other columns
usage_df2['total_energy'] = usage_df2.sum(axis=1)
cols = ['{}_mmbtu'.format(bu.change_name(col)) for col in usage_df2.columns]
usage_df2.columns = cols
usage_df2


Out[189]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu
fiscal_year
2006 24.719940 NaN NaN 0.0 24.719940
2007 630.537600 NaN NaN 0.0 630.537600
2008 708.924675 NaN NaN 0.0 708.924675
2009 656.786639 4472.297100 264.465 0.0 5393.548739
2010 641.697942 4416.021590 NaN 0.0 5057.719531
2011 664.086865 5203.093510 NaN 0.0 5867.180376
2012 683.037908 4183.582316 NaN 0.0 4866.620224
2013 600.549539 3545.521645 NaN 0.0 4146.071185
2014 616.351563 2163.879000 NaN 0.0 2780.230563
2015 664.534768 2082.877839 NaN 0.0 2747.412607
2016 595.196414 2151.683625 NaN 0.0 2746.880039
2017 880.345629 2112.299698 NaN 0.0 2992.645327
2018 113.573073 186.531677 NaN 0.0 300.104750

In [190]:
# Create a list of columns to loop through and calculate percent total energy
usage_cols = list(usage_df2.columns.values)
print (usage_cols)
usage_cols.remove('total_energy_mmbtu')

for col in usage_cols:
    col_name = col.split('_mmbtu')[0] + "_pct"
    usage_df2[col_name] = usage_df2[col] / usage_df2.total_energy_mmbtu

usage_df2


['electricity_mmbtu', 'natural_gas_mmbtu', 'fuel_oil_mmbtu', 'district_heat_mmbtu', 'total_energy_mmbtu']
Out[190]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu electricity_pct natural_gas_pct fuel_oil_pct district_heat_pct
fiscal_year
2006 24.719940 NaN NaN 0.0 24.719940 1.000000 NaN NaN 0.0
2007 630.537600 NaN NaN 0.0 630.537600 1.000000 NaN NaN 0.0
2008 708.924675 NaN NaN 0.0 708.924675 1.000000 NaN NaN 0.0
2009 656.786639 4472.297100 264.465 0.0 5393.548739 0.121773 0.829194 0.049034 0.0
2010 641.697942 4416.021590 NaN 0.0 5057.719531 0.126875 0.873125 NaN 0.0
2011 664.086865 5203.093510 NaN 0.0 5867.180376 0.113187 0.886813 NaN 0.0
2012 683.037908 4183.582316 NaN 0.0 4866.620224 0.140352 0.859648 NaN 0.0
2013 600.549539 3545.521645 NaN 0.0 4146.071185 0.144848 0.855152 NaN 0.0
2014 616.351563 2163.879000 NaN 0.0 2780.230563 0.221691 0.778309 NaN 0.0
2015 664.534768 2082.877839 NaN 0.0 2747.412607 0.241877 0.758123 NaN 0.0
2016 595.196414 2151.683625 NaN 0.0 2746.880039 0.216681 0.783319 NaN 0.0
2017 880.345629 2112.299698 NaN 0.0 2992.645327 0.294170 0.705830 NaN 0.0
2018 113.573073 186.531677 NaN 0.0 300.104750 0.378445 0.621555 NaN 0.0

In [191]:
# Add in degree days
months_present = bu.months_present(usage_df1)
deg_days = ut.degree_days_yearly(months_present, site)
usage_df2['hdd'] = deg_days
usage_df2


Out[191]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu electricity_pct natural_gas_pct fuel_oil_pct district_heat_pct hdd
fiscal_year
2006 24.719940 NaN NaN 0.0 24.719940 1.000000 NaN NaN 0.0 206
2007 630.537600 NaN NaN 0.0 630.537600 1.000000 NaN NaN 0.0 14075
2008 708.924675 NaN NaN 0.0 708.924675 1.000000 NaN NaN 0.0 13382
2009 656.786639 4472.297100 264.465 0.0 5393.548739 0.121773 0.829194 0.049034 0.0 14471
2010 641.697942 4416.021590 NaN 0.0 5057.719531 0.126875 0.873125 NaN 0.0 13119
2011 664.086865 5203.093510 NaN 0.0 5867.180376 0.113187 0.886813 NaN 0.0 13667
2012 683.037908 4183.582316 NaN 0.0 4866.620224 0.140352 0.859648 NaN 0.0 13960
2013 600.549539 3545.521645 NaN 0.0 4146.071185 0.144848 0.855152 NaN 0.0 14939
2014 616.351563 2163.879000 NaN 0.0 2780.230563 0.221691 0.778309 NaN 0.0 12531
2015 664.534768 2082.877839 NaN 0.0 2747.412607 0.241877 0.758123 NaN 0.0 12345
2016 595.196414 2151.683625 NaN 0.0 2746.880039 0.216681 0.783319 NaN 0.0 12017
2017 880.345629 2112.299698 NaN 0.0 2992.645327 0.294170 0.705830 NaN 0.0 13802
2018 113.573073 186.531677 NaN 0.0 300.104750 0.378445 0.621555 NaN 0.0 858

In [192]:
# Add in a column to show the numbers of months present for each year
# This will help to identify partial years.
mo_count = bu.month_count(months_present)
usage_df2['month_count'] = mo_count
usage_df2


Out[192]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu electricity_pct natural_gas_pct fuel_oil_pct district_heat_pct hdd month_count
fiscal_year
2006 24.719940 NaN NaN 0.0 24.719940 1.000000 NaN NaN 0.0 206 1
2007 630.537600 NaN NaN 0.0 630.537600 1.000000 NaN NaN 0.0 14075 12
2008 708.924675 NaN NaN 0.0 708.924675 1.000000 NaN NaN 0.0 13382 12
2009 656.786639 4472.297100 264.465 0.0 5393.548739 0.121773 0.829194 0.049034 0.0 14471 12
2010 641.697942 4416.021590 NaN 0.0 5057.719531 0.126875 0.873125 NaN 0.0 13119 12
2011 664.086865 5203.093510 NaN 0.0 5867.180376 0.113187 0.886813 NaN 0.0 13667 12
2012 683.037908 4183.582316 NaN 0.0 4866.620224 0.140352 0.859648 NaN 0.0 13960 12
2013 600.549539 3545.521645 NaN 0.0 4146.071185 0.144848 0.855152 NaN 0.0 14939 12
2014 616.351563 2163.879000 NaN 0.0 2780.230563 0.221691 0.778309 NaN 0.0 12531 12
2015 664.534768 2082.877839 NaN 0.0 2747.412607 0.241877 0.758123 NaN 0.0 12345 12
2016 595.196414 2151.683625 NaN 0.0 2746.880039 0.216681 0.783319 NaN 0.0 12017 12
2017 880.345629 2112.299698 NaN 0.0 2992.645327 0.294170 0.705830 NaN 0.0 13802 12
2018 113.573073 186.531677 NaN 0.0 300.104750 0.378445 0.621555 NaN 0.0 858 3

In [193]:
# Calculate total heat energy and normalized heating usage
usage_df2['total_heat_mmbtu'] = usage_df2.natural_gas_mmbtu + usage_df2.district_heat_mmbtu + usage_df2.fuel_oil_mmbtu
usage_df2['total_specific_heat'] = usage_df2.total_heat_mmbtu * 1000 / usage_df2.hdd
usage_df2 = usage_df2.query("month_count == 12")
usage_df2


Out[193]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu electricity_pct natural_gas_pct fuel_oil_pct district_heat_pct hdd month_count total_heat_mmbtu total_specific_heat
fiscal_year
2007 630.537600 NaN NaN 0.0 630.537600 1.000000 NaN NaN 0.0 14075 12 NaN NaN
2008 708.924675 NaN NaN 0.0 708.924675 1.000000 NaN NaN 0.0 13382 12 NaN NaN
2009 656.786639 4472.297100 264.465 0.0 5393.548739 0.121773 0.829194 0.049034 0.0 14471 12 4736.7621 327.327904
2010 641.697942 4416.021590 NaN 0.0 5057.719531 0.126875 0.873125 NaN 0.0 13119 12 NaN NaN
2011 664.086865 5203.093510 NaN 0.0 5867.180376 0.113187 0.886813 NaN 0.0 13667 12 NaN NaN
2012 683.037908 4183.582316 NaN 0.0 4866.620224 0.140352 0.859648 NaN 0.0 13960 12 NaN NaN
2013 600.549539 3545.521645 NaN 0.0 4146.071185 0.144848 0.855152 NaN 0.0 14939 12 NaN NaN
2014 616.351563 2163.879000 NaN 0.0 2780.230563 0.221691 0.778309 NaN 0.0 12531 12 NaN NaN
2015 664.534768 2082.877839 NaN 0.0 2747.412607 0.241877 0.758123 NaN 0.0 12345 12 NaN NaN
2016 595.196414 2151.683625 NaN 0.0 2746.880039 0.216681 0.783319 NaN 0.0 12017 12 NaN NaN
2017 880.345629 2112.299698 NaN 0.0 2992.645327 0.294170 0.705830 NaN 0.0 13802 12 NaN NaN

In [194]:
# Reverse the DataFrame
usage_df2.sort_index(ascending=False, inplace=True)
usage_df2 = usage_df2.drop('month_count', axis=1)
usage_df2


C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  from ipykernel import kernelapp as app
Out[194]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu electricity_pct natural_gas_pct fuel_oil_pct district_heat_pct hdd total_heat_mmbtu total_specific_heat
fiscal_year
2017 880.345629 2112.299698 NaN 0.0 2992.645327 0.294170 0.705830 NaN 0.0 13802 NaN NaN
2016 595.196414 2151.683625 NaN 0.0 2746.880039 0.216681 0.783319 NaN 0.0 12017 NaN NaN
2015 664.534768 2082.877839 NaN 0.0 2747.412607 0.241877 0.758123 NaN 0.0 12345 NaN NaN
2014 616.351563 2163.879000 NaN 0.0 2780.230563 0.221691 0.778309 NaN 0.0 12531 NaN NaN
2013 600.549539 3545.521645 NaN 0.0 4146.071185 0.144848 0.855152 NaN 0.0 14939 NaN NaN
2012 683.037908 4183.582316 NaN 0.0 4866.620224 0.140352 0.859648 NaN 0.0 13960 NaN NaN
2011 664.086865 5203.093510 NaN 0.0 5867.180376 0.113187 0.886813 NaN 0.0 13667 NaN NaN
2010 641.697942 4416.021590 NaN 0.0 5057.719531 0.126875 0.873125 NaN 0.0 13119 NaN NaN
2009 656.786639 4472.297100 264.465 0.0 5393.548739 0.121773 0.829194 0.049034 0.0 14471 4736.7621 327.327904
2008 708.924675 NaN NaN 0.0 708.924675 1.000000 NaN NaN 0.0 13382 NaN NaN
2007 630.537600 NaN NaN 0.0 630.537600 1.000000 NaN NaN 0.0 14075 NaN NaN

Create Energy Usage Overview Graphs


In [195]:
# Reset the index so the fiscal year column can be passed to the graphing function
reset_usage_df2 = usage_df2.reset_index()

p4g2_filename, p4g2_url = gu.graph_filename_url(site, 'annual_energy_usage_distribution')

# Create the area graph
gu.area_use_distribution(reset_usage_df2, 'fiscal_year', usage_cols, p4g2_filename)


C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\pyplot.py:524: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
  max_open_warning, RuntimeWarning)

In [196]:
p4g1_filename, p4g1_url = gu.graph_filename_url(site, "annual_energy_usage")

gu.energy_use_stacked_bar(reset_usage_df2, 'fiscal_year', usage_cols, p4g1_filename)

In [197]:
# Convert df to dictionary
energy_use_overview_rows = bu.df_to_dictionaries(usage_df2)

# Add data and graphs to main dictionary
template_data['energy_usage_overview'] = dict(
    graphs=[p4g1_url, p4g2_url],
    table={'rows': energy_use_overview_rows},
)

Create Usage Pie Charts


In [202]:
p5g1_filename, p5g1_url = gu.graph_filename_url(site, "energy_usage")
gu.usage_pie_charts(usage_df2, usage_cols, 1, p5g1_filename, site)


C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\axes\_base.py:2917: UserWarning: Attempting to set identical left==right results
in singular transformations; automatically expanding.
left=0.75, right=0.75
  'left=%s, right=%s') % (left, right))
C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\axes\_base.py:3193: UserWarning: Attempting to set identical bottom==top results
in singular transformations; automatically expanding.
bottom=0.75, top=0.75
  'bottom=%s, top=%s') % (bottom, top))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-202-fe55168bc440> in <module>()
      1 p5g1_filename, p5g1_url = gu.graph_filename_url(site, "energy_usage")
----> 2 gu.usage_pie_charts(usage_df2, usage_cols, 1, p5g1_filename, site)

C:\Users\dustin\Documents\GitHub\fnsb-benchmark\graph_util.py in usage_pie_charts(df, use_or_cost_cols, chart_type, base_filename, site_id)
    381 
    382         # Save and show
--> 383         plt.savefig(final_fn)
    384         figs.append(fig)
    385 

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\pyplot.py in savefig(*args, **kwargs)
    695 def savefig(*args, **kwargs):
    696     fig = gcf()
--> 697     res = fig.savefig(*args, **kwargs)
    698     fig.canvas.draw_idle()   # need this if 'transparent=True' to reset colors
    699     return res

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\figure.py in savefig(self, *args, **kwargs)
   1571             self.set_frameon(frameon)
   1572 
-> 1573         self.canvas.print_figure(*args, **kwargs)
   1574 
   1575         if frameon:

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2250                 orientation=orientation,
   2251                 bbox_inches_restore=_bbox_inches_restore,
-> 2252                 **kwargs)
   2253         finally:
   2254             if bbox_inches and restore_bbox:

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\backends\backend_agg.py in print_png(self, filename_or_obj, *args, **kwargs)
    543 
    544     def print_png(self, filename_or_obj, *args, **kwargs):
--> 545         FigureCanvasAgg.draw(self)
    546         renderer = self.get_renderer()
    547         original_dpi = renderer.dpi

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\backends\backend_agg.py in draw(self)
    462 
    463         try:
--> 464             self.figure.draw(self.renderer)
    465         finally:
    466             RendererAgg.lock.release()

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     61     def draw_wrapper(artist, renderer, *args, **kwargs):
     62         before(artist, renderer)
---> 63         draw(artist, renderer, *args, **kwargs)
     64         after(artist, renderer)
     65 

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\figure.py in draw(self, renderer)
   1142 
   1143             mimage._draw_list_compositing_images(
-> 1144                 renderer, self, dsu, self.suppressComposite)
   1145 
   1146             renderer.close_group('figure')

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\image.py in _draw_list_compositing_images(renderer, parent, dsu, suppress_composite)
    137     if not_composite or not has_images:
    138         for zorder, a in dsu:
--> 139             a.draw(renderer)
    140     else:
    141         # Composite any adjacent images together

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     61     def draw_wrapper(artist, renderer, *args, **kwargs):
     62         before(artist, renderer)
---> 63         draw(artist, renderer, *args, **kwargs)
     64         after(artist, renderer)
     65 

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\axes\_base.py in draw(self, renderer, inframe)
   2424             renderer.stop_rasterizing()
   2425 
-> 2426         mimage._draw_list_compositing_images(renderer, self, dsu)
   2427 
   2428         renderer.close_group('axes')

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\image.py in _draw_list_compositing_images(renderer, parent, dsu, suppress_composite)
    137     if not_composite or not has_images:
    138         for zorder, a in dsu:
--> 139             a.draw(renderer)
    140     else:
    141         # Composite any adjacent images together

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     61     def draw_wrapper(artist, renderer, *args, **kwargs):
     62         before(artist, renderer)
---> 63         draw(artist, renderer, *args, **kwargs)
     64         after(artist, renderer)
     65 

C:\Anaconda2\envs\py35\lib\site-packages\matplotlib\text.py in draw(self, renderer)
    760             posy = float(textobj.convert_yunits(textobj._y))
    761             if not np.isfinite(posx) or not np.isfinite(posy):
--> 762                 raise ValueError("posx and posy should be finite values")
    763             posx, posy = trans.transform_point((posx, posy))
    764             canvasw, canvash = renderer.get_canvas_width_height()

ValueError: posx and posy should be finite values

In [ ]:
# Add pie charts to template dictionary
template_data['energy_cost_usage'] = dict(
    graphs=[p5g1_url])

Electrical Usage Analysis - Page 6


In [203]:
site_df = df.query("site_id == @site")
site_df.head()


Out[203]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
30353 ANSBG1 Electricity 2006 6 Energy charge kWh 739.280 16.5 7245.0 2006 12 24.71994
30354 ANSBG1 Electricity 2006 6 KW Charge kW 0.000 16.5 14.5 2006 12 0.00000
30355 ANSBG1 Electricity 2006 6 Other Charge - 183.065 16.5 NaN 2006 12 NaN
30356 ANSBG1 Electricity 2006 7 Energy charge kWh 1414.275 31.0 13860.0 2007 1 47.29032
30357 ANSBG1 Electricity 2006 7 KW Charge kW 0.000 31.0 29.5 2007 1 0.00000

In [204]:
# only look at elecricity records
electric_df = site_df.query("service_type == 'Electricity'")

In [205]:
# Make sure I'm not potentially missing anything with funky unit names
check_df = electric_df.query("usage > 0")
check_df.units.unique()


Out[205]:
array(['kWh', 'kW'], dtype=object)

In [206]:
electric_df = electric_df.query("units == 'kWh' or units == 'kW'")
electric_df.head()


Out[206]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
30353 ANSBG1 Electricity 2006 6 Energy charge kWh 739.280000 16.5 7245.0 2006 12 24.71994
30354 ANSBG1 Electricity 2006 6 KW Charge kW 0.000000 16.5 14.5 2006 12 0.00000
30356 ANSBG1 Electricity 2006 7 Energy charge kWh 1414.275000 31.0 13860.0 2007 1 47.29032
30357 ANSBG1 Electricity 2006 7 KW Charge kW 0.000000 31.0 29.5 2007 1 0.00000
30359 ANSBG1 Electricity 2006 8 Energy charge kWh 1432.643065 31.0 14040.0 2007 2 47.90448

In [207]:
electric_df.query("units == 'kWh'")['item_desc'].unique()


Out[207]:
array(['Energy charge', 'Utility Charge'], dtype=object)

In [208]:
electric_df.item_desc.unique()


Out[208]:
array(['Energy charge', 'KW Charge', 'Utility Charge'], dtype=object)

In [209]:
electric_pivot_monthly = pd.pivot_table(electric_df,
                                        index=['fiscal_year', 'fiscal_mo'], 
                                        columns=['units'],
                                        values='usage',
                                        aggfunc=np.sum)

electric_pivot_monthly.head()


Out[209]:
units kW kWh
fiscal_year fiscal_mo
2006 12 14.500000 7245.000000
2007 1 29.500000 13860.000000
2 29.903226 14040.000000
3 28.043203 10510.714286
4 28.763249 11772.027650

In [210]:
# Do a month count for the elecricity bills 
elec_months_present = bu.months_present(electric_pivot_monthly.reset_index())
elec_mo_count = bu.month_count(elec_months_present)
elec_mo_count_df = pd.DataFrame(elec_mo_count)
elec_mo_count_df


Out[210]:
month
year
2006 1
2007 12
2008 12
2009 12
2010 12
2011 12
2012 12
2013 12
2014 12
2015 12
2016 12
2017 12
2018 3

In [211]:
electric_pivot_annual = pd.pivot_table(electric_df,
                                       index=['fiscal_year'],
                                       columns=['units'],
                                       values='usage',
                                       aggfunc=np.sum
                                      )
                                       
electric_use_annual = electric_pivot_annual[['kWh']]
electric_use_annual = electric_use_annual.rename(columns={'kWh':'ann_electric_usage_kWh'})
electric_use_annual


Out[211]:
units ann_electric_usage_kWh
fiscal_year
2006 7245.000000
2007 184800.000000
2008 207773.937500
2009 192493.153409
2010 188070.909091
2011 194632.727273
2012 200186.960227
2013 176011.002155
2014 180642.310345
2015 194764.000000
2016 174442.090909
2017 258014.545455
2018 33286.363636

In [212]:
# Get average annual demand usage
electric_demand_avg = electric_pivot_monthly.groupby(['fiscal_year']).mean()
electric_demand_avg = electric_demand_avg[['kW']]
electric_demand_avg = electric_demand_avg.rename(columns={'kW': 'avg_demand_kW'})
electric_demand_avg


Out[212]:
units avg_demand_kW
fiscal_year
2006 14.500000
2007 31.128906
2008 32.985937
2009 31.425182
2010 30.372475
2011 32.692803
2012 33.901728
2013 16.671875
2014 NaN
2015 NaN
2016 NaN
2017 NaN
2018 NaN

In [213]:
# Find annual maximum demand usage
electric_demand_max = electric_pivot_monthly.groupby(['fiscal_year']).max()
electric_demand_max = electric_demand_max[['kW']]
electric_demand_max = electric_demand_max.rename(columns={'kW': 'max_demand_kW'})
electric_demand_max


Out[213]:
units max_demand_kW
fiscal_year
2006 14.500000
2007 36.607143
2008 37.793382
2009 35.030977
2010 33.789706
2011 38.700000
2012 38.550000
2013 17.637931
2014 NaN
2015 NaN
2016 NaN
2017 NaN
2018 NaN

In [214]:
# Combine dataframes
electric_demand_join = pd.merge(electric_demand_max, electric_demand_avg, how='outer', left_index=True, right_index=True)
annual_electric_data = pd.merge(electric_demand_join, electric_use_annual, how='outer', left_index=True, right_index=True)
annual_electric_data


Out[214]:
units max_demand_kW avg_demand_kW ann_electric_usage_kWh
fiscal_year
2006 14.500000 14.500000 7245.000000
2007 36.607143 31.128906 184800.000000
2008 37.793382 32.985937 207773.937500
2009 35.030977 31.425182 192493.153409
2010 33.789706 30.372475 188070.909091
2011 38.700000 32.692803 194632.727273
2012 38.550000 33.901728 200186.960227
2013 17.637931 16.671875 176011.002155
2014 NaN NaN 180642.310345
2015 NaN NaN 194764.000000
2016 NaN NaN 174442.090909
2017 NaN NaN 258014.545455
2018 NaN NaN 33286.363636

In [215]:
# Add percent change columns
annual_electric_data['usage_pct_change'] = annual_electric_data.ann_electric_usage_kWh.pct_change()
annual_electric_data['avg_demand_pct_change'] = annual_electric_data.avg_demand_kW.pct_change()
annual_electric_data['max_demand_pct_change'] = annual_electric_data.max_demand_kW.pct_change()
annual_electric_data = annual_electric_data.rename(columns={'avg_demand_kW': 'Average kW',
                                                           'ann_electric_usage_kWh': 'Total kWh'})
annual_electric_data = pd.merge(annual_electric_data, elec_mo_count_df, left_index=True, right_index=True, how='left')
annual_electric_data = annual_electric_data.query("month == 12")
annual_electric_data = annual_electric_data.sort_index(ascending=False)
annual_electric_data = annual_electric_data.rename(columns={'max_demand_kW':'kw_max',
                                                           'Average kW':'kw_avg',
                                                           'Total kWh':'kwh',
                                                           'usage_pct_change':'kwh_pct_change',
                                                           'avg_demand_pct_change':'kw_avg_pct_change',
                                                           'max_demand_pct_change':'kw_max_pct_change'})
annual_electric_data = annual_electric_data.drop('month', axis=1)
annual_electric_data


Out[215]:
kw_max kw_avg kwh kwh_pct_change kw_avg_pct_change kw_max_pct_change
fiscal_year
2017 NaN NaN 258014.545455 0.479084 NaN NaN
2016 NaN NaN 174442.090909 -0.104341 NaN NaN
2015 NaN NaN 194764.000000 0.078175 NaN NaN
2014 NaN NaN 180642.310345 0.026313 NaN NaN
2013 17.637931 16.671875 176011.002155 -0.120767 -0.508229 -0.542466
2012 38.550000 33.901728 200186.960227 0.028537 0.036978 -0.003876
2011 38.700000 32.692803 194632.727273 0.034890 0.076396 0.145319
2010 33.789706 30.372475 188070.909091 -0.022974 -0.033499 -0.035434
2009 35.030977 31.425182 192493.153409 -0.073545 -0.047316 -0.073092
2008 37.793382 32.985937 207773.937500 0.124318 0.059656 0.032405
2007 36.607143 31.128906 184800.000000 24.507246 1.146821 1.524631

Create Electrical Usage Analysis Graphs - Page 6


In [216]:
# Axes labels
ylabel1 = 'Electricity Usage [kWh]'
ylabel2 = 'Electricity Demand [kW]'

In [217]:
p6g1_filename, p6g1_url = gu.graph_filename_url(site, "electricity_usage")
gu.stacked_bar_with_line(annual_electric_data.reset_index(), 'fiscal_year', ['kwh'], 'kw_avg', 
                      ylabel1, ylabel2, "Test Title", p6g1_filename)

In [218]:
p6g2_filename, p6g2_url = gu.graph_filename_url(site, "monthly_electricity_usage_profile")
gu.create_monthly_profile(electric_pivot_monthly, 'kWh', 'Monthly Electricity Usage Profile [kWh]', 'blue',
                         "Test Title", p6g2_filename)

In [219]:
# Convert df to dictionary
electric_use_rows = bu.df_to_dictionaries(annual_electric_data)

# Add data and graphs to main dictionary
template_data['electrical_usage_analysis'] = dict(
    graphs=[p6g1_url, p6g2_url],
    table={'rows': electric_use_rows},
)

Electrical Cost Analysis Table - Page 7


In [220]:
# only look at elecricity records
electric_cost_df = site_df.query("service_type == 'Electricity'")

In [221]:
electric_cost_df.item_desc.unique()


Out[221]:
array(['Energy charge', 'KW Charge', 'Other Charge', 'On peak demand',
       'Utility Charge'], dtype=object)

In [222]:
# Costs don't always have units, so split the data into demand charges and usage charges (which includes other charges)
electric_cost_df['cost_categories'] = np.where(electric_cost_df.item_desc.isin(['KW Charge', 'On peak demand', 'Demand Charge']),
                                               'demand_cost', 'usage_cost')


C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  app.launch_new_instance()

In [223]:
# Sum costs by demand and usage
electric_annual_cost = pd.pivot_table(electric_cost_df,
                                       index=['fiscal_year'],
                                       columns=['cost_categories'],
                                       values='cost',
                                       aggfunc=np.sum
                                      )
# Create a total column
electric_annual_cost['Total Cost'] = electric_annual_cost.demand_cost + electric_annual_cost.usage_cost

electric_annual_cost


Out[223]:
cost_categories demand_cost usage_cost Total Cost
fiscal_year
2006 0.0 922.345000 922.345000
2007 0.0 24319.055469 24319.055469
2008 0.0 33274.530938 33274.530938
2009 0.0 30307.350563 30307.350563
2010 0.0 32688.293030 32688.293030
2011 0.0 35138.080909 35138.080909
2012 0.0 41994.697841 41994.697841
2013 0.0 36961.451595 36961.451595
2014 0.0 35843.822155 35843.822155
2015 NaN 38017.419167 NaN
2016 NaN 32391.098485 NaN
2017 NaN 54161.057879 NaN
2018 NaN 7256.446970 NaN

In [224]:
# Add percent change columns
electric_annual_cost['usage_cost_pct_change'] = electric_annual_cost.usage_cost.pct_change()
electric_annual_cost['demand_cost_pct_change'] = electric_annual_cost.demand_cost.pct_change()
electric_annual_cost['total_cost_pct_change'] = electric_annual_cost['Total Cost'].pct_change()
electric_annual_cost


Out[224]:
cost_categories demand_cost usage_cost Total Cost usage_cost_pct_change demand_cost_pct_change total_cost_pct_change
fiscal_year
2006 0.0 922.345000 922.345000 NaN NaN NaN
2007 0.0 24319.055469 24319.055469 25.366550 NaN 25.366550
2008 0.0 33274.530938 33274.530938 0.368249 NaN 0.368249
2009 0.0 30307.350563 30307.350563 -0.089173 NaN -0.089173
2010 0.0 32688.293030 32688.293030 0.078560 NaN 0.078560
2011 0.0 35138.080909 35138.080909 0.074944 NaN 0.074944
2012 0.0 41994.697841 41994.697841 0.195134 NaN 0.195134
2013 0.0 36961.451595 36961.451595 -0.119854 NaN -0.119854
2014 0.0 35843.822155 35843.822155 -0.030238 NaN -0.030238
2015 NaN 38017.419167 NaN 0.060641 NaN NaN
2016 NaN 32391.098485 NaN -0.147993 NaN NaN
2017 NaN 54161.057879 NaN 0.672097 NaN NaN
2018 NaN 7256.446970 NaN -0.866021 NaN NaN

In [225]:
# Left join the cost data to the annual electric data, which only shows complete years
electric_use_and_cost = pd.merge(annual_electric_data, electric_annual_cost, left_index=True, right_index=True, how='left')
electric_use_and_cost = electric_use_and_cost.sort_index(ascending=False)
electric_use_and_cost = electric_use_and_cost.drop(['kw_max', 'kw_max_pct_change'], axis=1)
electric_use_and_cost = electric_use_and_cost.rename(columns={'demand_cost':'kw_avg_cost',
                                                              'usage_cost':'kwh_cost',
                                                              'Total Cost':'total_cost',
                                                              'usage_cost_pct_change':'kwh_cost_pct_change',
                                                              'demand_cost_pct_change':'kw_avg_cost_pct_change'
                                                             })
electric_use_and_cost


Out[225]:
kw_avg kwh kwh_pct_change kw_avg_pct_change kw_avg_cost kwh_cost total_cost kwh_cost_pct_change kw_avg_cost_pct_change total_cost_pct_change
fiscal_year
2017 NaN 258014.545455 0.479084 NaN NaN 54161.057879 NaN 0.672097 NaN NaN
2016 NaN 174442.090909 -0.104341 NaN NaN 32391.098485 NaN -0.147993 NaN NaN
2015 NaN 194764.000000 0.078175 NaN NaN 38017.419167 NaN 0.060641 NaN NaN
2014 NaN 180642.310345 0.026313 NaN 0.0 35843.822155 35843.822155 -0.030238 NaN -0.030238
2013 16.671875 176011.002155 -0.120767 -0.508229 0.0 36961.451595 36961.451595 -0.119854 NaN -0.119854
2012 33.901728 200186.960227 0.028537 0.036978 0.0 41994.697841 41994.697841 0.195134 NaN 0.195134
2011 32.692803 194632.727273 0.034890 0.076396 0.0 35138.080909 35138.080909 0.074944 NaN 0.074944
2010 30.372475 188070.909091 -0.022974 -0.033499 0.0 32688.293030 32688.293030 0.078560 NaN 0.078560
2009 31.425182 192493.153409 -0.073545 -0.047316 0.0 30307.350563 30307.350563 -0.089173 NaN -0.089173
2008 32.985937 207773.937500 0.124318 0.059656 0.0 33274.530938 33274.530938 0.368249 NaN 0.368249
2007 31.128906 184800.000000 24.507246 1.146821 0.0 24319.055469 24319.055469 25.366550 NaN 25.366550

Create Electrical Cost Analysis Graphs - Page 7


In [226]:
p7g1_filename, p7g1_url = gu.graph_filename_url(site, "electricity_cost")

renamed_use_and_cost = electric_use_and_cost.rename(columns={'kwh_cost':'Electricity Usage Cost [$]',
                                                            'kw_avg_cost':'Electricity Demand Cost [$]'})
gu.create_stacked_bar(renamed_use_and_cost.reset_index(), 'fiscal_year', ['Electricity Usage Cost [$]', 
                                                                          'Electricity Demand Cost [$]'], 
                      'Electricity Cost [$]', "test title", p7g1_filename)

In [227]:
# Create Monthly Profile of Electricity Demand
p7g2_filename, p7g2_url = gu.graph_filename_url(site, "monthly_electricity_demand_profile")
gu.create_monthly_profile(electric_pivot_monthly, 'kW', 'Monthly Electricity Demand Profile [kW]', 'blue', 
                          "test title", p7g2_filename)

In [228]:
# Convert df to dictionary
electric_cost_rows = bu.df_to_dictionaries(electric_use_and_cost)

# Add data and graphs to main dictionary
template_data['electrical_cost_analysis'] = dict(
    graphs=[p7g1_url, p7g2_url],
    table={'rows': electric_cost_rows},
)

Create Heating Usage Analysis Table - Page 8


In [229]:
usage_df2.head()


Out[229]:
electricity_mmbtu natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu total_energy_mmbtu electricity_pct natural_gas_pct fuel_oil_pct district_heat_pct hdd total_heat_mmbtu total_specific_heat
fiscal_year
2017 880.345629 2112.299698 NaN 0.0 2992.645327 0.294170 0.705830 NaN 0.0 13802 NaN NaN
2016 595.196414 2151.683625 NaN 0.0 2746.880039 0.216681 0.783319 NaN 0.0 12017 NaN NaN
2015 664.534768 2082.877839 NaN 0.0 2747.412607 0.241877 0.758123 NaN 0.0 12345 NaN NaN
2014 616.351563 2163.879000 NaN 0.0 2780.230563 0.221691 0.778309 NaN 0.0 12531 NaN NaN
2013 600.549539 3545.521645 NaN 0.0 4146.071185 0.144848 0.855152 NaN 0.0 14939 NaN NaN

In [230]:
# Take only needed columns from earlier usage df
heating_usage = usage_df2[['natural_gas_mmbtu', 'fuel_oil_mmbtu', 'district_heat_mmbtu', 'hdd', 'total_heat_mmbtu']]
heating_usage


Out[230]:
natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu hdd total_heat_mmbtu
fiscal_year
2017 2112.299698 NaN 0.0 13802 NaN
2016 2151.683625 NaN 0.0 12017 NaN
2015 2082.877839 NaN 0.0 12345 NaN
2014 2163.879000 NaN 0.0 12531 NaN
2013 3545.521645 NaN 0.0 14939 NaN
2012 4183.582316 NaN 0.0 13960 NaN
2011 5203.093510 NaN 0.0 13667 NaN
2010 4416.021590 NaN 0.0 13119 NaN
2009 4472.297100 264.465 0.0 14471 4736.7621
2008 NaN NaN 0.0 13382 NaN
2007 NaN NaN 0.0 14075 NaN

In [231]:
# Add in percent change columns
heating_usage['fuel_oil_pct_change'] = heating_usage.fuel_oil_mmbtu.pct_change()
heating_usage['natural_gas_pct_change'] = heating_usage.natural_gas_mmbtu.pct_change()
heating_usage['district_heat_pct_change'] = heating_usage.district_heat_mmbtu.pct_change()
heating_usage['total_heat_pct_change'] = heating_usage.total_heat_mmbtu.pct_change()
heating_usage


C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  from ipykernel import kernelapp as app
C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  app.launch_new_instance()
C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:4: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:5: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
Out[231]:
natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu hdd total_heat_mmbtu fuel_oil_pct_change natural_gas_pct_change district_heat_pct_change total_heat_pct_change
fiscal_year
2017 2112.299698 NaN 0.0 13802 NaN NaN NaN NaN NaN
2016 2151.683625 NaN 0.0 12017 NaN NaN 0.018645 NaN NaN
2015 2082.877839 NaN 0.0 12345 NaN NaN -0.031978 NaN NaN
2014 2163.879000 NaN 0.0 12531 NaN NaN 0.038889 NaN NaN
2013 3545.521645 NaN 0.0 14939 NaN NaN 0.638503 NaN NaN
2012 4183.582316 NaN 0.0 13960 NaN NaN 0.179962 NaN NaN
2011 5203.093510 NaN 0.0 13667 NaN NaN 0.243693 NaN NaN
2010 4416.021590 NaN 0.0 13119 NaN NaN -0.151270 NaN NaN
2009 4472.297100 264.465 0.0 14471 4736.7621 NaN 0.012743 NaN NaN
2008 NaN NaN 0.0 13382 NaN NaN NaN NaN NaN
2007 NaN NaN 0.0 14075 NaN NaN NaN NaN NaN

In [232]:
# Get the number of gallons, ccf, and 1,000 pounds of district heat by converting MMBTUs using the supplied conversions
heating_usage['fuel_oil_usage'] = heating_usage.fuel_oil_mmbtu * 1000000 / ut.fuel_btus_per_unit('Oil #1', 'gallons')
heating_usage['natural_gas_usage'] = heating_usage.natural_gas_mmbtu * 1000000 / ut.fuel_btus_per_unit('Natural Gas', 'ccf')
heating_usage


C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  from ipykernel import kernelapp as app
C:\Anaconda2\envs\py35\lib\site-packages\ipykernel\__main__.py:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  app.launch_new_instance()
Out[232]:
natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu hdd total_heat_mmbtu fuel_oil_pct_change natural_gas_pct_change district_heat_pct_change total_heat_pct_change fuel_oil_usage natural_gas_usage
fiscal_year
2017 2112.299698 NaN 0.0 13802 NaN NaN NaN NaN NaN NaN 20708.820565
2016 2151.683625 NaN 0.0 12017 NaN NaN 0.018645 NaN NaN NaN 21094.937500
2015 2082.877839 NaN 0.0 12345 NaN NaN -0.031978 NaN NaN NaN 20420.370968
2014 2163.879000 NaN 0.0 12531 NaN NaN 0.038889 NaN NaN NaN 21214.500000
2013 3545.521645 NaN 0.0 14939 NaN NaN 0.638503 NaN NaN NaN 34760.016129
2012 4183.582316 NaN 0.0 13960 NaN NaN 0.179962 NaN NaN NaN 41015.512903
2011 5203.093510 NaN 0.0 13667 NaN NaN 0.243693 NaN NaN NaN 51010.720690
2010 4416.021590 NaN 0.0 13119 NaN NaN -0.151270 NaN NaN NaN 43294.329310
2009 4472.297100 264.465 0.0 14471 4736.7621 NaN 0.012743 NaN NaN 1959.0 43846.050000
2008 NaN NaN 0.0 13382 NaN NaN NaN NaN NaN NaN NaN
2007 NaN NaN 0.0 14075 NaN NaN NaN NaN NaN NaN NaN

Create Heating Usage Analysis Graphs - Page 8


In [233]:
p8g1_filename, p8g1_url = gu.graph_filename_url(site, "heating_degree_days")
gu.stacked_bar_with_line(heating_usage.reset_index(), 'fiscal_year', ['natural_gas_mmbtu', 'fuel_oil_mmbtu',
                                                                                'district_heat_mmbtu'], 'hdd',
                        'Heating Fuel Usage [MMBTU/yr]', 'Heating Degree Days [Base 65F]', "test title", p8g1_filename)

Create Monthly Heating Usage dataframe for graph


In [234]:
monthly_heating = pd.pivot_table(usage_df1,
                                values='mmbtu',
                                index=['fiscal_year', 'fiscal_mo'],
                                columns=['service_type'],
                                aggfunc=np.sum
                                )
monthly_heating.head()


Out[234]:
service_type Electricity Natural Gas Oil #1 Sewer Water
fiscal_year fiscal_mo
2006 12 24.719940 NaN NaN NaN NaN
2007 1 47.290320 NaN NaN NaN NaN
2 47.904480 NaN NaN NaN NaN
3 35.862557 NaN NaN NaN NaN
4 40.166158 NaN NaN 0.0 0.0

In [235]:
monthly_heating


Out[235]:
service_type Electricity Natural Gas Oil #1 Sewer Water
fiscal_year fiscal_mo
2006 12 24.719940 NaN NaN NaN NaN
2007 1 47.290320 NaN NaN NaN NaN
2 47.904480 NaN NaN NaN NaN
3 35.862557 NaN NaN NaN NaN
4 40.166158 NaN NaN 0.0 0.0
5 54.319685 NaN NaN 0.0 0.0
6 60.303120 NaN NaN 0.0 0.0
7 63.518595 NaN NaN 0.0 0.0
8 58.795584 NaN NaN 0.0 0.0
9 64.179720 NaN NaN 0.0 0.0
10 56.958387 NaN NaN 0.0 0.0
11 53.136190 NaN NaN 0.0 0.0
12 48.102803 NaN NaN 0.0 0.0
2008 1 52.242838 NaN NaN 0.0 0.0
2 52.908178 NaN NaN 0.0 0.0
3 55.847616 NaN NaN 0.0 0.0
4 59.781962 NaN NaN 0.0 0.0
5 59.776636 NaN NaN 0.0 0.0
6 64.680717 NaN NaN 0.0 0.0
7 66.030885 NaN NaN 0.0 0.0
8 63.405314 NaN NaN 0.0 0.0
9 64.430439 NaN NaN 0.0 0.0
10 59.032663 NaN NaN 0.0 0.0
11 59.058308 NaN NaN 0.0 0.0
12 51.729119 NaN NaN 0.0 0.0
2009 1 53.572025 NaN NaN 0.0 0.0
2 53.333592 27.683438 NaN 0.0 0.0
3 51.050942 335.507963 NaN 0.0 0.0
4 59.193452 544.017319 NaN 0.0 0.0
5 60.000138 445.134375 NaN 0.0 0.0
... ... ... ... ... ... ...
2015 10 53.844772 134.187481 NaN 0.0 0.0
11 52.968658 117.290437 NaN 0.0 0.0
12 51.022278 132.298781 NaN 0.0 0.0
2016 1 50.030156 135.585968 NaN 0.0 0.0
2 48.348040 112.488232 NaN 0.0 0.0
3 46.539680 115.033436 NaN 0.0 0.0
4 46.385074 192.115455 NaN 0.0 0.0
5 47.479046 245.582199 NaN 0.0 0.0
6 52.092208 274.768258 NaN 0.0 0.0
7 55.470503 242.785245 NaN 0.0 0.0
8 55.094640 245.192626 NaN 0.0 0.0
9 54.725571 210.813381 NaN 0.0 0.0
10 48.445997 165.976265 NaN 0.0 0.0
11 47.549632 128.628635 NaN 0.0 0.0
12 43.035866 82.713925 NaN 0.0 0.0
2017 1 45.154829 84.978750 NaN 0.0 0.0
2 47.180192 132.593625 NaN 0.0 0.0
3 42.324312 120.670935 NaN 0.0 0.0
4 68.221289 205.955165 NaN 0.0 0.0
5 95.780723 207.063400 NaN 0.0 0.0
6 99.895470 262.274903 NaN 0.0 0.0
7 111.586593 303.225847 NaN 0.0 0.0
8 103.200814 199.574105 NaN 0.0 0.0
9 102.974160 242.359109 NaN 0.0 0.0
10 76.762689 168.507808 NaN 0.0 0.0
11 47.059892 102.898527 NaN 0.0 0.0
12 40.204667 82.197523 NaN 0.0 0.0
2018 1 44.681137 96.413032 NaN 0.0 0.0
2 45.710406 90.118645 NaN 0.0 0.0
3 23.181529 NaN NaN 0.0 0.0

136 rows × 5 columns


In [236]:
# Add in columns for the missing energy services
missing_services = bu.missing_energy_services(monthly_heating.columns)
bu.add_columns(monthly_heating, missing_services)

# Drop the non-heating services
monthly_heating = monthly_heating.drop(labels=['Electricity', 'Sewer', 'Water'], axis=1)

# Create a total heating column
monthly_heating['total_heating_energy'] = monthly_heating.sum(axis=1)

monthly_heating.head()


Out[236]:
service_type Natural Gas Oil #1 Steam total_heating_energy
fiscal_year fiscal_mo
2006 12 NaN NaN 0.0 0.0
2007 1 NaN NaN 0.0 0.0
2 NaN NaN 0.0 0.0
3 NaN NaN 0.0 0.0
4 NaN NaN 0.0 0.0

In [237]:
p8g2_filename, p8g2_url = gu.graph_filename_url(site, "monthly_heating_energy_profile")
gu.create_monthly_profile(monthly_heating, 'total_heating_energy', "Monthly Heating Energy Profile [MMBTU]", 'red',
                          "test title", p8g2_filename)

In [238]:
# Convert df to dictionary
heating_use_rows = bu.df_to_dictionaries(heating_usage)

# Add data and graphs to main dictionary
template_data['heating_usage_analysis'] = dict(
    graphs=[p8g1_url, p8g2_url],
    table={'rows': heating_use_rows},
)

Heating Cost Analysis Table - Page 9


In [239]:
# Import df that I exported from "alan_report_pages".  This can be removed once code is combined
df2 = pd.read_csv(r"C:\Users\dustin\Google Drive\FNSB Data Analysis\data_from_alan_report_pages_df2.csv")

# Use only necessary columns
heating_cost = df2[['fiscal_year', 'Natural Gas', 'Oil #1', 'Steam', 'Total', 'pct_change']]

# Change column names so they aren't the same as the heating usage dataframe
heating_cost = heating_cost.rename(columns={'Natural Gas':'natural_gas_cost',
                                           'Oil #1': 'fuel_oil_cost',
                                           'Steam': 'district_heat_cost',
                                           'Total': 'total_heat_cost',
                                           'pct_change': 'total_heat_cost_pct_change'})
heating_cost


Out[239]:
fiscal_year natural_gas_cost fuel_oil_cost district_heat_cost total_heat_cost total_heat_cost_pct_change
0 2017 53336.961562 29028.075000 0.0 294496.131925 -0.211853
1 2016 690.478276 90349.225000 0.0 373656.286356 -0.090911
2 2015 97125.406774 48709.171396 0.0 411022.962057 -0.127236
3 2014 164359.650963 15747.134827 0.0 470943.816735 -0.073340
4 2013 173104.449037 20369.326596 0.0 508216.253007 0.048115
5 2012 163613.406387 17351.334533 0.0 484885.747289 0.157875
6 2011 20902.767000 139185.262647 0.0 418772.262631 NaN

In [240]:
heating_usage


Out[240]:
natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu hdd total_heat_mmbtu fuel_oil_pct_change natural_gas_pct_change district_heat_pct_change total_heat_pct_change fuel_oil_usage natural_gas_usage
fiscal_year
2017 2112.299698 NaN 0.0 13802 NaN NaN NaN NaN NaN NaN 20708.820565
2016 2151.683625 NaN 0.0 12017 NaN NaN 0.018645 NaN NaN NaN 21094.937500
2015 2082.877839 NaN 0.0 12345 NaN NaN -0.031978 NaN NaN NaN 20420.370968
2014 2163.879000 NaN 0.0 12531 NaN NaN 0.038889 NaN NaN NaN 21214.500000
2013 3545.521645 NaN 0.0 14939 NaN NaN 0.638503 NaN NaN NaN 34760.016129
2012 4183.582316 NaN 0.0 13960 NaN NaN 0.179962 NaN NaN NaN 41015.512903
2011 5203.093510 NaN 0.0 13667 NaN NaN 0.243693 NaN NaN NaN 51010.720690
2010 4416.021590 NaN 0.0 13119 NaN NaN -0.151270 NaN NaN NaN 43294.329310
2009 4472.297100 264.465 0.0 14471 4736.7621 NaN 0.012743 NaN NaN 1959.0 43846.050000
2008 NaN NaN 0.0 13382 NaN NaN NaN NaN NaN NaN NaN
2007 NaN NaN 0.0 14075 NaN NaN NaN NaN NaN NaN NaN

In [241]:
# Combine the heating cost and heating use dataframes
heating_cost_and_use = pd.merge(heating_cost, heating_usage, left_on='fiscal_year', right_index=True, how='right')
heating_cost_and_use


Out[241]:
fiscal_year natural_gas_cost fuel_oil_cost district_heat_cost total_heat_cost total_heat_cost_pct_change natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu hdd total_heat_mmbtu fuel_oil_pct_change natural_gas_pct_change district_heat_pct_change total_heat_pct_change fuel_oil_usage natural_gas_usage
0 2017 53336.961562 29028.075000 0.0 294496.131925 -0.211853 2112.299698 NaN 0.0 13802 NaN NaN NaN NaN NaN NaN 20708.820565
1 2016 690.478276 90349.225000 0.0 373656.286356 -0.090911 2151.683625 NaN 0.0 12017 NaN NaN 0.018645 NaN NaN NaN 21094.937500
2 2015 97125.406774 48709.171396 0.0 411022.962057 -0.127236 2082.877839 NaN 0.0 12345 NaN NaN -0.031978 NaN NaN NaN 20420.370968
3 2014 164359.650963 15747.134827 0.0 470943.816735 -0.073340 2163.879000 NaN 0.0 12531 NaN NaN 0.038889 NaN NaN NaN 21214.500000
4 2013 173104.449037 20369.326596 0.0 508216.253007 0.048115 3545.521645 NaN 0.0 14939 NaN NaN 0.638503 NaN NaN NaN 34760.016129
5 2012 163613.406387 17351.334533 0.0 484885.747289 0.157875 4183.582316 NaN 0.0 13960 NaN NaN 0.179962 NaN NaN NaN 41015.512903
6 2011 20902.767000 139185.262647 0.0 418772.262631 NaN 5203.093510 NaN 0.0 13667 NaN NaN 0.243693 NaN NaN NaN 51010.720690
6 2010 NaN NaN NaN NaN NaN 4416.021590 NaN 0.0 13119 NaN NaN -0.151270 NaN NaN NaN 43294.329310
6 2009 NaN NaN NaN NaN NaN 4472.297100 264.465 0.0 14471 4736.7621 NaN 0.012743 NaN NaN 1959.0 43846.050000
6 2008 NaN NaN NaN NaN NaN NaN NaN 0.0 13382 NaN NaN NaN NaN NaN NaN NaN
6 2007 NaN NaN NaN NaN NaN NaN NaN 0.0 14075 NaN NaN NaN NaN NaN NaN NaN

In [242]:
# Create percent change columns
heating_cost_and_use['fuel_oil_pct_change'] = heating_cost_and_use.fuel_oil_cost.pct_change()
heating_cost_and_use['natural_gas_pct_change'] = heating_cost_and_use.natural_gas_cost.pct_change()
heating_cost_and_use['district_heat_pct_change'] = heating_cost_and_use.district_heat_cost.pct_change()

In [243]:
# Create unit cost columns
heating_cost_and_use['fuel_oil_unit_cost'] = heating_cost_and_use.fuel_oil_cost / heating_cost_and_use.fuel_oil_mmbtu
heating_cost_and_use['natural_gas_unit_cost'] = heating_cost_and_use.natural_gas_cost / heating_cost_and_use.natural_gas_mmbtu
heating_cost_and_use['district_heat_unit_cost'] = heating_cost_and_use.district_heat_cost / heating_cost_and_use.district_heat_mmbtu
heating_cost_and_use['building_heat_unit_cost'] = heating_cost_and_use.total_heat_cost / heating_cost_and_use.total_heat_mmbtu
heating_cost_and_use


Out[243]:
fiscal_year natural_gas_cost fuel_oil_cost district_heat_cost total_heat_cost total_heat_cost_pct_change natural_gas_mmbtu fuel_oil_mmbtu district_heat_mmbtu hdd ... fuel_oil_pct_change natural_gas_pct_change district_heat_pct_change total_heat_pct_change fuel_oil_usage natural_gas_usage fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_heat_unit_cost
0 2017 53336.961562 29028.075000 0.0 294496.131925 -0.211853 2112.299698 NaN 0.0 13802 ... NaN NaN NaN NaN NaN 20708.820565 NaN 25.250660 NaN NaN
1 2016 690.478276 90349.225000 0.0 373656.286356 -0.090911 2151.683625 NaN 0.0 12017 ... 2.112477 -0.987054 NaN NaN NaN 21094.937500 NaN 0.320901 NaN NaN
2 2015 97125.406774 48709.171396 0.0 411022.962057 -0.127236 2082.877839 NaN 0.0 12345 ... -0.460879 139.663957 NaN NaN NaN 20420.370968 NaN 46.630390 NaN NaN
3 2014 164359.650963 15747.134827 0.0 470943.816735 -0.073340 2163.879000 NaN 0.0 12531 ... -0.676711 0.692242 NaN NaN NaN 21214.500000 NaN 75.956027 NaN NaN
4 2013 173104.449037 20369.326596 0.0 508216.253007 0.048115 3545.521645 NaN 0.0 14939 ... 0.293526 0.053205 NaN NaN NaN 34760.016129 NaN 48.823408 NaN NaN
5 2012 163613.406387 17351.334533 0.0 484885.747289 0.157875 4183.582316 NaN 0.0 13960 ... -0.148164 -0.054828 NaN NaN NaN 41015.512903 NaN 39.108447 NaN NaN
6 2011 20902.767000 139185.262647 0.0 418772.262631 NaN 5203.093510 NaN 0.0 13667 ... 7.021588 -0.872243 NaN NaN NaN 51010.720690 NaN 4.017373 NaN NaN
6 2010 NaN NaN NaN NaN NaN 4416.021590 NaN 0.0 13119 ... NaN NaN NaN NaN NaN 43294.329310 NaN NaN NaN NaN
6 2009 NaN NaN NaN NaN NaN 4472.297100 264.465 0.0 14471 ... NaN NaN NaN NaN 1959.0 43846.050000 NaN NaN NaN NaN
6 2008 NaN NaN NaN NaN NaN NaN NaN 0.0 13382 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 2007 NaN NaN NaN NaN NaN NaN NaN 0.0 14075 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

11 rows × 21 columns


In [244]:
# Remove all columns not needed for the Heating Cost Analysis Table
heating_cost_and_use = heating_cost_and_use[['fiscal_year',
                                              'fuel_oil_cost',
                                              'fuel_oil_pct_change',
                                              'natural_gas_cost',
                                              'natural_gas_pct_change',
                                              'district_heat_cost',
                                              'district_heat_pct_change',
                                              'fuel_oil_unit_cost',
                                              'natural_gas_unit_cost',
                                              'district_heat_unit_cost',
                                              'building_heat_unit_cost',
                                              'total_heat_cost',
                                              'total_heat_cost_pct_change']]

heating_cost_and_use


Out[244]:
fiscal_year fuel_oil_cost fuel_oil_pct_change natural_gas_cost natural_gas_pct_change district_heat_cost district_heat_pct_change fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_heat_unit_cost total_heat_cost total_heat_cost_pct_change
0 2017 29028.075000 NaN 53336.961562 NaN 0.0 NaN NaN 25.250660 NaN NaN 294496.131925 -0.211853
1 2016 90349.225000 2.112477 690.478276 -0.987054 0.0 NaN NaN 0.320901 NaN NaN 373656.286356 -0.090911
2 2015 48709.171396 -0.460879 97125.406774 139.663957 0.0 NaN NaN 46.630390 NaN NaN 411022.962057 -0.127236
3 2014 15747.134827 -0.676711 164359.650963 0.692242 0.0 NaN NaN 75.956027 NaN NaN 470943.816735 -0.073340
4 2013 20369.326596 0.293526 173104.449037 0.053205 0.0 NaN NaN 48.823408 NaN NaN 508216.253007 0.048115
5 2012 17351.334533 -0.148164 163613.406387 -0.054828 0.0 NaN NaN 39.108447 NaN NaN 484885.747289 0.157875
6 2011 139185.262647 7.021588 20902.767000 -0.872243 0.0 NaN NaN 4.017373 NaN NaN 418772.262631 NaN
6 2010 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 2009 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 2008 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 2007 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

Create DataFrame with the Monthly Average Price Per MMBTU for All Sites


In [245]:
print (df.shape[0])

# Filter out natural gas customer charges as the unit cost goes to infinity if there is a charge but no use
df_no_gas_cust_charges = df.drop(df[(df['service_type'] == 'Natural Gas') & (df['units'] != 'CCF')].index)

# Filter out records with zero usage, which correspond to things like customer charges, etc.
nonzero_usage = df_no_gas_cust_charges.query("usage > 0")
print (nonzero_usage.shape[0])
nonzero_usage.head()


74268
37607
Out[245]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
0 03 Electricity 2005 12 Electricity charge kWh 1904.657880 49.5 14790.748577 2006 6 50.466034
1 03 Electricity 2006 1 Electricity charge kWh 5430.493797 93.0 42665.790911 2006 7 145.575679
2 03 Electricity 2006 2 Electricity charge kWh 5764.406730 84.0 45010.439348 2006 8 153.575619
3 03 Electricity 2006 3 Electricity charge kWh 6349.255299 93.0 46311.547557 2006 9 158.015000
4 03 Electricity 2006 4 Electricity charge kWh 5529.385224 90.0 40392.812893 2006 10 137.820278

In [246]:
# Check to make sure it is okay to drop records w/ zero mmbtu
zero_mmbtu = nonzero_usage.query("mmbtu == 0")
zero_mmbtu.service_type.unique()


Out[246]:
array(['Refuse', 'Water', 'Electricity', 'Sewer'], dtype=object)

In [247]:
nonzero_usage = nonzero_usage.query("mmbtu > 0")
print (nonzero_usage.shape[0])
nonzero_usage.head()


21159
Out[247]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
0 03 Electricity 2005 12 Electricity charge kWh 1904.657880 49.5 14790.748577 2006 6 50.466034
1 03 Electricity 2006 1 Electricity charge kWh 5430.493797 93.0 42665.790911 2006 7 145.575679
2 03 Electricity 2006 2 Electricity charge kWh 5764.406730 84.0 45010.439348 2006 8 153.575619
3 03 Electricity 2006 3 Electricity charge kWh 6349.255299 93.0 46311.547557 2006 9 158.015000
4 03 Electricity 2006 4 Electricity charge kWh 5529.385224 90.0 40392.812893 2006 10 137.820278

In [248]:
nonzero_usage.cost.min()


Out[248]:
-15844.611451612904

In [249]:
# Further analysis showed that these zero and less than zero costs were for waste oil; presumably less than zero costs
# was because they were able to avoid disposal fees or something
nonzero_usage.query("cost <= 0")


Out[249]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
280 03 Natural Gas 2009 12 Natural gas (CCF) CCF 0.000000 1.5 0.051724 2010 6 0.005276
283 03 Natural Gas 2010 1 Natural gas (CCF) CCF 0.000000 27.5 0.948276 2010 7 0.096724
15895 23 Oil #1 2010 6 Fuel Oil #1 (Gallons) Gallons -15844.611452 29.5 6420.774194 2010 12 866.804516
25351 43 Steam 2008 10 Steam (klbs) klbs 0.000000 31.0 240.414747 2009 4 287.055207
25352 43 Steam 2008 11 Steam (klbs) klbs 0.000000 30.0 239.870968 2009 5 286.405935
25353 43 Steam 2008 12 Steam (klbs) klbs 0.000000 31.0 240.129032 2009 6 286.714065
25354 43 Steam 2009 1 Steam (klbs) klbs 0.000000 31.0 240.000000 2009 7 286.560000
25355 43 Steam 2009 2 Steam (klbs) klbs 0.000000 28.0 239.585253 2009 8 286.064793
25356 43 Steam 2009 3 Steam (klbs) klbs 0.000000 31.0 240.414747 2009 9 287.055207
25357 43 Steam 2009 4 Steam (klbs) klbs 0.000000 30.0 239.870968 2009 10 286.405935
42186 BENBG1 Oil #1 2011 9 Fuel Oil #1 (Gallons) Gallons -16.703818 40.5 132.880397 2012 3 17.938854
42188 BENBG1 Oil #1 2011 10 Fuel Oil #1 (Gallons) Gallons -249.442449 50.5 185.006122 2012 4 24.975827

In [250]:
# Looks like waste oil accounts for the negative costs
BALHHW = df_raw[(df_raw['Site ID'] == 'BALHHW')].sort_values(by='Cost')
BALHHW[BALHHW['Service Name'] == 'Oil #1']


Out[250]:
Site ID Site Name Vendor Code Vendor Name Account Number Bill Date Due Date Entry Date Invoice # Voucher # From Thru Service Name Item Description Meter Number Usage Cost Units Account Financial Code Site Financial Code
82088 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 03/10/2016 03/10/2016 10/11/2017 NaN NaN 2016-03-09 2016-03-10 Oil #1 Fuel Oil #1 (Gallons) NaN -500.1 -768.85 NaN NaN NaN
21078 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 07/31/2006 07/31/2006 04/08/2011 NaN NaN 2006-07-01 2006-07-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1569.0 0.00 Gallons NaN NaN
21178 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 11/30/2014 11/30/2014 09/28/2015 NaN NaN 2014-10-31 2014-11-30 Oil #1 Fuel Oil #1 (Gallons) NaN 3330.0 0.00 Gallons NaN NaN
21177 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 10/31/2014 10/31/2014 09/28/2015 NaN NaN 2014-09-30 2014-10-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1435.0 0.00 Gallons NaN NaN
21176 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 09/30/2014 09/30/2014 09/28/2015 NaN NaN 2014-08-31 2014-09-30 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
21175 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 08/31/2014 08/31/2014 09/28/2015 NaN NaN 2014-07-31 2014-08-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1314.0 0.00 Gallons NaN NaN
21174 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 07/31/2014 07/31/2014 09/28/2015 NaN NaN 2014-06-30 2014-07-31 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
21173 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 06/30/2014 06/30/2014 09/28/2015 NaN NaN 2014-05-31 2014-06-30 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
21172 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 05/31/2014 05/31/2014 09/28/2015 NaN NaN 2014-04-30 2014-05-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1632.0 0.00 Gallons NaN NaN
21171 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 04/30/2014 04/30/2014 09/28/2015 NaN NaN 2014-03-31 2014-04-30 Oil #1 Fuel Oil #1 (Gallons) NaN 568.0 0.00 Gallons NaN NaN
21170 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 03/31/2014 03/31/2014 09/28/2015 NaN NaN 2014-02-28 2014-03-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1568.0 0.00 Gallons NaN NaN
21169 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 02/28/2014 02/28/2014 09/28/2015 NaN NaN 2014-01-31 2014-02-28 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
21168 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 01/31/2014 01/31/2014 09/28/2015 NaN NaN 2013-12-31 2014-01-31 Oil #1 Fuel Oil #1 (Gallons) NaN 2624.0 0.00 Gallons NaN NaN
21167 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 12/31/2013 12/31/2013 09/28/2015 NaN NaN 2013-11-30 2013-12-31 Oil #1 Fuel Oil #1 (Gallons) NaN 3786.0 0.00 Gallons NaN NaN
21166 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 11/30/2013 11/30/2013 09/28/2015 NaN NaN 2013-10-31 2013-11-30 Oil #1 Fuel Oil #1 (Gallons) NaN 3469.0 0.00 Gallons NaN NaN
21165 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 10/31/2013 10/31/2013 09/28/2015 NaN NaN 2013-09-30 2013-10-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1562.0 0.00 Gallons NaN NaN
21179 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 12/31/2014 12/31/2014 09/28/2015 NaN NaN 2014-11-30 2014-12-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1378.0 0.00 Gallons NaN NaN
21164 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 09/30/2013 09/30/2013 09/28/2015 NaN NaN 2013-08-31 2013-09-30 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
21162 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 07/31/2013 07/31/2013 09/28/2015 NaN NaN 2013-06-30 2013-07-31 Oil #1 Fuel Oil #1 (Gallons) NaN 2414.0 0.00 Gallons NaN NaN
21161 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 06/30/2013 06/30/2013 09/28/2015 NaN NaN 2013-05-31 2013-06-30 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
21160 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 05/31/2013 05/31/2013 09/28/2015 NaN NaN 2013-04-30 2013-05-31 Oil #1 Fuel Oil #1 (Gallons) NaN 69.0 0.00 Gallons NaN NaN
21159 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 04/30/2013 04/30/2013 09/28/2015 NaN NaN 2013-03-31 2013-04-30 Oil #1 Fuel Oil #1 (Gallons) NaN 904.0 0.00 Gallons NaN NaN
21158 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 03/31/2013 03/31/2013 09/28/2015 NaN NaN 2013-02-28 2013-03-31 Oil #1 Fuel Oil #1 (Gallons) NaN 3769.0 0.00 Gallons NaN NaN
21157 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 02/28/2013 02/28/2013 03/26/2013 NaN NaN 2013-01-31 2013-02-28 Oil #1 Fuel Oil #1 (Gallons) NaN 1905.0 0.00 Gallons NaN NaN
21156 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 01/31/2013 01/31/2013 03/26/2013 NaN NaN 2012-12-31 2013-01-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1259.0 0.00 Gallons NaN NaN
21155 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 12/31/2012 12/31/2012 03/26/2013 NaN NaN 2012-11-30 2012-12-31 Oil #1 Fuel Oil #1 (Gallons) NaN 5002.0 0.00 Gallons NaN NaN
21154 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 11/30/2012 11/30/2012 03/26/2013 NaN NaN 2012-10-31 2012-11-30 Oil #1 Fuel Oil #1 (Gallons) NaN 1625.0 0.00 Gallons NaN NaN
21153 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 10/31/2012 10/31/2012 03/26/2013 NaN NaN 2012-09-30 2012-10-31 Oil #1 Fuel Oil #1 (Gallons) NaN 1286.0 0.00 Gallons NaN NaN
21152 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 09/30/2012 09/30/2012 12/03/2012 NaN NaN 2012-08-31 2012-09-30 Oil #1 Fuel Oil #1 (Gallons) NaN 737.0 0.00 Gallons NaN NaN
21151 BALHHW FNSB-Solid Waste Baler/Office/HHW WO Waste Oil 1234 08/31/2012 08/31/2012 12/03/2012 NaN NaN 2012-07-31 2012-08-31 Oil #1 Fuel Oil #1 (Gallons) NaN 0.0 0.00 NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
82067 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/27/2015 02/27/2015 10/11/2017 NaN NaN 2015-02-13 2015-02-27 Oil #1 Fuel Oil #1 (Gallons) NaN 1240.9 3031.40 Gallons NaN NaN
82073 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 06/24/2015 06/24/2015 10/11/2017 NaN NaN 2015-05-07 2015-06-24 Oil #1 Fuel Oil #1 (Gallons) NaN 1184.4 3118.40 Gallons NaN NaN
82017 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 11/09/2012 11/09/2012 07/31/2014 NaN NaN 2012-10-26 2012-11-09 Oil #1 Fuel Oil #1 (Gallons) NaN 917.0 3145.65 Gallons NaN NaN
82035 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/01/2013 02/01/2013 07/23/2014 NaN NaN 2013-01-18 2013-02-01 Oil #1 Fuel Oil #1 (Gallons) NaN 937.0 3223.62 Gallons NaN NaN
81993 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 04/09/2012 04/09/2012 08/03/2012 NaN NaN 2012-03-26 2012-04-09 Oil #1 Fuel Oil #1 (Gallons) NaN 881.0 3304.13 Gallons NaN NaN
82054 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 03/24/2014 03/24/2014 10/11/2017 NaN NaN 2014-03-10 2014-03-24 Oil #1 Fuel Oil #1 (Gallons) NaN 1023.8 3412.22 Gallons NaN NaN
81905 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 12/06/2006 12/06/2006 02/10/2011 NaN NaN 2006-08-29 2006-12-06 Oil #1 Fuel Oil #1 (Gallons) NaN 1782.0 3500.84 Gallons NaN NaN
82068 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 03/13/2015 03/13/2015 10/11/2017 NaN NaN 2015-02-27 2015-03-13 Oil #1 Fuel Oil #1 (Gallons) NaN 1405.9 3603.18 Gallons NaN NaN
81947 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 12/23/2010 12/23/2010 02/15/2011 NaN NaN 2010-11-26 2010-12-23 Oil #1 Fuel Oil #1 (Gallons) NaN 1246.0 3638.90 Gallons NaN NaN
81913 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 12/13/2007 12/13/2007 02/10/2011 NaN NaN 2007-09-27 2007-12-13 Oil #1 Fuel Oil #1 (Gallons) NaN 1300.0 3659.50 Gallons NaN NaN
81972 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 01/04/2012 01/04/2012 01/06/2012 NaN NaN 2011-12-08 2012-01-04 Oil #1 Fuel Oil #1 (Gallons) NaN 1137.0 3763.47 Gallons NaN NaN
82023 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 12/07/2012 12/07/2012 08/05/2014 NaN NaN 2012-11-23 2012-12-07 Oil #1 Fuel Oil #1 (Gallons) NaN 1198.0 3957.04 Gallons NaN NaN
81975 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 01/18/2012 01/18/2012 01/27/2012 NaN NaN 2012-01-04 2012-01-18 Oil #1 Fuel Oil #1 (Gallons) NaN 1203.0 4160.65 Gallons NaN NaN
81990 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 03/26/2012 03/26/2012 08/03/2012 NaN NaN 2012-03-12 2012-03-26 Oil #1 Fuel Oil #1 (Gallons) NaN 1140.0 4273.50 Gallons NaN NaN
82066 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/13/2015 02/13/2015 10/11/2017 NaN NaN 2015-01-27 2015-02-13 Oil #1 Fuel Oil #1 (Gallons) NaN 1821.3 4303.55 Gallons NaN NaN
82051 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/10/2014 02/10/2014 10/11/2017 NaN NaN 2014-01-27 2014-02-10 Oil #1 Fuel Oil #1 (Gallons) NaN 1251.3 4333.13 Gallons NaN NaN
81984 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/27/2012 02/27/2012 08/02/2012 NaN NaN 2012-02-13 2012-02-27 Oil #1 Fuel Oil #1 (Gallons) NaN 1199.0 4363.63 Gallons NaN NaN
82005 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 09/14/2012 09/14/2012 08/12/2014 NaN NaN 2012-05-21 2012-09-14 Oil #1 Fuel Oil #1 (Gallons) NaN 1220.0 4365.81 Gallons NaN NaN
82089 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/22/2017 02/22/2017 10/11/2017 NaN NaN 2016-03-10 2017-02-22 Oil #1 Fuel Oil #1 (Gallons) NaN 2500.1 4919.31 Gallons NaN NaN
82090 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 04/13/2017 04/13/2017 10/11/2017 NaN NaN 2017-02-22 2017-04-13 Oil #1 Fuel Oil #1 (Gallons) NaN 2788.1 5179.29 Gallons NaN NaN
81987 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 03/12/2012 03/12/2012 08/03/2012 NaN NaN 2012-02-27 2012-03-12 Oil #1 Fuel Oil #1 (Gallons) NaN 1415.0 5233.65 Gallons NaN NaN
82052 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/24/2014 02/24/2014 10/11/2017 NaN NaN 2014-02-10 2014-02-24 Oil #1 Fuel Oil #1 (Gallons) NaN 1520.2 5264.30 Gallons NaN NaN
81978 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 01/28/2012 01/28/2012 02/02/2012 NaN NaN 2012-01-18 2012-01-28 Oil #1 Fuel Oil #1 (Gallons) NaN 1600.0 5376.00 Gallons NaN NaN
82060 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 11/03/2014 11/03/2014 10/11/2017 NaN NaN 2014-07-18 2014-11-03 Oil #1 Fuel Oil #1 (Gallons) NaN 1728.6 5519.24 Gallons NaN NaN
81919 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 01/27/2009 01/27/2009 02/11/2011 NaN NaN 2008-12-10 2009-01-27 Oil #1 Fuel Oil #1 (Gallons) NaN 3019.0 5540.05 Gallons NaN NaN
81969 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 12/08/2011 12/08/2011 12/19/2011 NaN NaN 2011-11-10 2011-12-08 Oil #1 Fuel Oil #1 (Gallons) NaN 1602.0 5542.92 Gallons NaN NaN
81981 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 02/13/2012 02/13/2012 08/02/2012 NaN NaN 2012-01-28 2012-02-13 Oil #1 Fuel Oil #1 (Gallons) NaN 1700.0 5933.00 Gallons NaN NaN
81963 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 10/13/2011 10/13/2011 12/13/2013 NaN NaN 2011-04-25 2011-10-13 Oil #1 Fuel Oil #1 (Gallons) NaN 1775.0 6212.15 Gallons NaN NaN
81911 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 09/27/2007 09/27/2007 02/10/2011 NaN NaN 2007-04-12 2007-09-27 Oil #1 Fuel Oil #1 (Gallons) NaN 2998.0 7149.04 Gallons NaN NaN
82047 BALHHW FNSB-Solid Waste Baler/Office/HHW VP287678 Sourdough Fuel (Petro Star) 39389003 (LANDFILL OFF) 10/09/2013 10/09/2013 10/11/2017 NaN NaN 2013-05-06 2013-10-09 Oil #1 Fuel Oil #1 (Gallons) NaN 2791.7 9360.29 Gallons NaN NaN

296 rows × 20 columns


In [251]:
# No idea why these costs are negative but it still seems like it should be filtered out
df_raw[(df_raw['Site ID'] == 'BENBG1')].sort_values(by='Cost')


Out[251]:
Site ID Site Name Vendor Code Vendor Name Account Number Bill Date Due Date Entry Date Invoice # Voucher # From Thru Service Name Item Description Meter Number Usage Cost Units Account Financial Code Site Financial Code
82569 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 10/20/2011 10/20/2011 04/09/2013 NaN NaN 2011-09-20 2011-10-20 Oil #1 Fuel Oil #1 (Gallons) NaN 198.0 -694.40 Gallons NaN NaN
82571 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 10/20/2011 10/20/2011 04/09/2013 NaN NaN 2011-09-20 2011-10-20 Oil #1 Misc. fee NaN NaN -0.40 NaN NaN NaN
82570 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 10/20/2011 10/20/2011 04/09/2013 NaN NaN 2011-09-20 2011-10-20 Oil #1 FED LUS TX NaN NaN -0.20 NaN NaN NaN
66899 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 05/08/2009 05/08/2009 02/09/2011 NaN NaN 2009-04-07 2009-05-07 Electricity Fuel Adjustment NaN NaN 0.00 NaN NaN NaN
66895 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 04/08/2009 04/08/2009 02/09/2011 NaN NaN 2009-03-09 2009-04-07 Electricity Fuel Adjustment NaN NaN 0.00 NaN NaN NaN
66891 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 03/11/2009 03/11/2009 02/09/2011 NaN NaN 2009-02-06 2009-03-09 Electricity Fuel Adjustment NaN NaN 0.00 NaN NaN NaN
82558 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/07/2009 11/07/2009 02/11/2011 NaN NaN 2009-02-19 2009-11-07 Oil #1 FED LUS TX NaN NaN 0.04 NaN NaN NaN
82585 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/27/2012 02/27/2012 08/03/2012 NaN NaN 2012-02-03 2012-02-27 Oil #1 FED LUS TX NaN NaN 0.06 NaN NaN NaN
82588 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/26/2012 03/26/2012 08/03/2012 NaN NaN 2012-02-27 2012-03-26 Oil #1 FED LUS TX NaN NaN 0.07 NaN NaN NaN
82550 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/26/2007 11/26/2007 02/10/2011 NaN NaN 2007-08-09 2007-11-26 Oil #1 FED LUS TX NaN NaN 0.07 NaN NaN NaN
82554 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/18/2008 11/18/2008 02/10/2011 NaN NaN 2008-03-04 2008-11-18 Oil #1 FED LUS TX NaN NaN 0.07 NaN NaN NaN
82562 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/02/2010 11/02/2010 02/15/2011 NaN NaN 2010-02-10 2010-11-02 Oil #1 FED LUS TX NaN NaN 0.08 NaN NaN NaN
82576 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 12/02/2011 12/02/2011 12/20/2011 NaN NaN 2011-11-08 2011-12-02 Oil #1 FED LUS TX NaN NaN 0.08 NaN NaN NaN
82573 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/08/2011 11/08/2011 12/19/2011 NaN NaN 2011-09-20 2011-11-08 Oil #1 FED LUS TX NaN NaN 0.09 NaN NaN NaN
82546 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/24/2006 11/24/2006 02/10/2011 NaN NaN 2006-03-03 2006-11-24 Oil #1 FED LUS TX NaN NaN 0.09 NaN NaN NaN
82586 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/27/2012 02/27/2012 08/03/2012 NaN NaN 2012-02-03 2012-02-27 Oil #1 Misc. fee NaN NaN 0.11 NaN NaN NaN
82582 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/03/2012 02/03/2012 08/03/2012 NaN NaN 2012-01-07 2012-02-03 Oil #1 FED LUS TX NaN NaN 0.11 NaN NaN NaN
82579 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 01/07/2012 01/07/2012 01/26/2012 NaN NaN 2011-12-02 2012-01-07 Oil #1 FED LUS TX NaN NaN 0.11 NaN NaN NaN
82589 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/26/2012 03/26/2012 08/03/2012 NaN NaN 2012-02-27 2012-03-26 Oil #1 Misc. fee NaN NaN 0.14 NaN NaN NaN
82552 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/04/2008 03/04/2008 02/11/2011 NaN NaN 2007-11-26 2008-03-04 Oil #1 FED LUS TX NaN NaN 0.14 NaN NaN NaN
82556 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/19/2009 02/19/2009 02/11/2011 NaN NaN 2008-11-18 2009-02-19 Oil #1 FED LUS TX NaN NaN 0.14 NaN NaN NaN
82560 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/10/2010 02/10/2010 02/11/2011 NaN NaN 2009-11-07 2010-02-10 Oil #1 FED LUS TX NaN NaN 0.15 NaN NaN NaN
82577 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 12/02/2011 12/02/2011 12/20/2011 NaN NaN 2011-11-08 2011-12-02 Oil #1 Misc. fee NaN NaN 0.16 NaN NaN NaN
82564 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/09/2011 02/09/2011 03/11/2011 NaN NaN 2010-11-02 2011-02-09 Oil #1 FED LUS TX NaN NaN 0.17 NaN NaN NaN
82574 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/08/2011 11/08/2011 12/19/2011 NaN NaN 2011-09-20 2011-11-08 Oil #1 Misc. fee NaN NaN 0.18 NaN NaN NaN
82591 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/17/2012 11/17/2012 04/09/2013 NaN NaN 2012-03-26 2012-11-17 Oil #1 FED LUS TX NaN NaN 0.18 NaN NaN NaN
82548 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/09/2007 03/09/2007 02/10/2011 NaN NaN 2006-11-24 2007-03-09 Oil #1 FED LUS TX NaN NaN 0.19 NaN NaN NaN
82594 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 01/23/2013 01/23/2013 04/09/2013 NaN NaN 2012-11-17 2013-01-23 Oil #1 FED LUS TX NaN NaN 0.20 NaN NaN NaN
82583 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/03/2012 02/03/2012 08/03/2012 NaN NaN 2012-01-07 2012-02-03 Oil #1 Misc. fee NaN NaN 0.22 NaN NaN NaN
82580 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 01/07/2012 01/07/2012 01/26/2012 NaN NaN 2011-12-02 2012-01-07 Oil #1 Misc. fee NaN NaN 0.23 NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
82555 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/19/2009 02/19/2009 02/11/2011 NaN NaN 2008-11-18 2009-02-19 Oil #1 Fuel Oil #1 (Gallons) NaN 142.0 261.30 Gallons NaN NaN
82601 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 07/18/2014 07/18/2014 10/11/2017 NaN NaN 2014-03-01 2014-07-18 Oil #1 Fuel Oil #1 (Gallons) NaN 75.0 263.47 Gallons NaN NaN
66804 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 02/08/2007 02/08/2007 04/20/2011 NaN NaN 2007-01-08 2007-02-08 Electricity Energy charge NaN 1922.0 264.13 kWh NaN NaN
66882 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 01/12/2009 01/12/2009 02/09/2011 NaN NaN 2008-12-05 2009-01-08 Electricity Energy charge NaN 2461.0 275.36 kWh NaN NaN
66802 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 12/08/2006 12/08/2006 04/20/2011 NaN NaN 2006-11-07 2006-12-07 Electricity Energy charge NaN 2014.0 275.82 kWh NaN NaN
66838 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 02/11/2008 02/11/2008 02/09/2011 NaN NaN 2008-01-08 2008-02-08 Electricity Energy charge NaN 2532.0 277.43 kWh NaN NaN
82587 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/26/2012 03/26/2012 08/03/2012 NaN NaN 2012-02-27 2012-03-26 Oil #1 Fuel Oil #1 (Gallons) NaN 72.0 278.74 Gallons NaN NaN
82575 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 12/02/2011 12/02/2011 12/20/2011 NaN NaN 2011-11-08 2011-12-02 Oil #1 Fuel Oil #1 (Gallons) NaN 80.0 283.81 Gallons NaN NaN
66834 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 01/09/2008 01/09/2008 02/09/2011 NaN NaN 2007-12-06 2008-01-08 Electricity Energy charge NaN 2827.0 309.75 kWh NaN NaN
82572 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/08/2011 11/08/2011 12/19/2011 NaN NaN 2011-09-20 2011-11-08 Oil #1 Fuel Oil #1 (Gallons) NaN 89.0 319.16 Gallons NaN NaN
82604 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 06/24/2015 06/24/2015 10/11/2017 NaN NaN 2015-03-13 2015-06-24 Oil #1 Fuel Oil #1 (Gallons) NaN 117.9 322.21 Gallons NaN NaN
82547 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/09/2007 03/09/2007 02/10/2011 NaN NaN 2006-11-24 2007-03-09 Oil #1 Fuel Oil #1 (Gallons) NaN 189.0 355.89 Gallons NaN NaN
82559 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/10/2010 02/10/2010 02/11/2011 NaN NaN 2009-11-07 2010-02-10 Oil #1 Fuel Oil #1 (Gallons) NaN 150.0 359.25 Gallons NaN NaN
82578 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 01/07/2012 01/07/2012 01/26/2012 NaN NaN 2011-12-02 2012-01-07 Oil #1 Fuel Oil #1 (Gallons) NaN 114.0 376.02 Gallons NaN NaN
82581 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/03/2012 02/03/2012 08/03/2012 NaN NaN 2012-01-07 2012-02-03 Oil #1 Fuel Oil #1 (Gallons) NaN 109.0 377.83 Gallons NaN NaN
66803 BENBG1 FNSB-Solid Waste Entrance Scales VG354933 Golden Valley Electric 28219 01/09/2007 01/09/2007 04/20/2011 NaN NaN 2006-12-07 2007-01-08 Electricity Energy charge NaN 2945.0 394.08 kWh NaN NaN
82551 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/04/2008 03/04/2008 02/11/2011 NaN NaN 2007-11-26 2008-03-04 Oil #1 Fuel Oil #1 (Gallons) NaN 135.0 401.63 Gallons NaN NaN
82606 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/29/2016 03/29/2016 10/11/2017 NaN NaN 2015-12-23 2016-03-29 Oil #1 Fuel Oil #1 (Gallons) NaN 271.4 444.40 Gallons NaN NaN
82607 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/30/2016 11/30/2016 10/11/2017 NaN NaN 2016-03-29 2016-11-30 Oil #1 Fuel Oil #1 (Gallons) NaN 255.8 455.95 Gallons NaN NaN
82608 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/17/2017 02/17/2017 10/11/2017 NaN NaN 2016-11-30 2017-02-17 Oil #1 Fuel Oil #1 (Gallons) NaN 235.0 462.40 Gallons NaN NaN
82563 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 02/09/2011 02/09/2011 03/11/2011 NaN NaN 2010-11-02 2011-02-09 Oil #1 Fuel Oil #1 (Gallons) NaN 165.0 513.15 Gallons NaN NaN
82605 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 12/23/2015 12/23/2015 10/11/2017 NaN NaN 2015-06-24 2015-12-23 Oil #1 Fuel Oil #1 (Gallons) NaN 297.8 526.34 Gallons NaN NaN
82599 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 12/13/2013 12/13/2013 10/11/2017 NaN NaN 2013-05-02 2013-12-13 Oil #1 Fuel Oil #1 (Gallons) NaN 174.4 602.18 Gallons NaN NaN
82590 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 11/17/2012 11/17/2012 04/09/2013 NaN NaN 2012-03-26 2012-11-17 Oil #1 Fuel Oil #1 (Gallons) NaN 181.0 629.53 Gallons NaN NaN
82600 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/01/2014 03/01/2014 10/11/2017 NaN NaN 2013-12-13 2014-03-01 Oil #1 Fuel Oil #1 (Gallons) NaN 193.7 690.13 Gallons NaN NaN
82603 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 03/13/2015 03/13/2015 10/11/2017 NaN NaN 2014-12-18 2015-03-13 Oil #1 Fuel Oil #1 (Gallons) NaN 262.8 699.81 Gallons NaN NaN
82593 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 01/23/2013 01/23/2013 04/09/2013 NaN NaN 2012-11-17 2013-01-23 Oil #1 Fuel Oil #1 (Gallons) NaN 200.0 703.05 Gallons NaN NaN
82602 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 12/18/2014 12/18/2014 10/11/2017 NaN NaN 2014-07-18 2014-12-18 Oil #1 Fuel Oil #1 (Gallons) NaN 261.0 788.98 Gallons NaN NaN
82596 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 05/02/2013 05/02/2013 07/23/2013 NaN NaN 2013-01-23 2013-05-02 Oil #1 Fuel Oil #1 (Gallons) NaN 257.0 860.28 Gallons NaN NaN
82566 BENBG1 FNSB-Solid Waste Entrance Scales VP287678 Sourdough Fuel (Petro Star) 39389009 (SCALES) 09/20/2011 09/20/2011 12/19/2011 NaN NaN 2011-02-09 2011-09-20 Oil #1 Fuel Oil #1 (Gallons) NaN 509.0 1806.24 Gallons NaN NaN

284 rows × 20 columns


In [252]:
# Filter out zero cost or less records (see analysis above)
nonzero_usage = nonzero_usage.query("cost > 0")

In [253]:
# Get the total fuel cost and usage for all buildings by year and month
grouped_nonzero_usage = nonzero_usage.groupby(['service_type', 'fiscal_year', 'fiscal_mo']).sum()

# Divide the total cost for all building by the total usage for all buildings so that the average is weighted correctly
grouped_nonzero_usage['avg_price_per_mmbtu'] = grouped_nonzero_usage.cost / grouped_nonzero_usage.mmbtu

# Get only the desired outcome, price per million BTU for each fuel type, and the number of calendar months it is based on
# i.e. the number of months of bills for each fuel for all buildings for that particular month.
grouped_nonzero_usage = grouped_nonzero_usage[['avg_price_per_mmbtu', 'cal_mo']]

In [254]:
# Drop electricity from the dataframe.
grouped_nonzero_usage = grouped_nonzero_usage.reset_index()
grouped_nonzero_heatfuel_use = grouped_nonzero_usage.query("service_type != 'Electricity'")

# Create a column for each service type
grouped_nonzero_heatfuel_use = pd.pivot_table(grouped_nonzero_heatfuel_use,
                                              values='avg_price_per_mmbtu',
                                              index=['fiscal_year', 'fiscal_mo'],
                                              columns='service_type'
                                                )
grouped_nonzero_heatfuel_use = grouped_nonzero_heatfuel_use.reset_index()

grouped_nonzero_heatfuel_use.head()


Out[254]:
service_type fiscal_year fiscal_mo Natural Gas Oil #1 Steam
0 2006 2 NaN 17.464387 NaN
1 2006 3 NaN 17.464387 NaN
2 2006 4 NaN 17.464387 NaN
3 2006 5 NaN 17.464387 11.374288
4 2006 6 12.480403 17.464387 9.529815

Monthly Cost Per MMBTU: Data and Graphs - Page 9


In [255]:
raw_oil = df_raw[(df_raw['Service Name'] == 'Oil #1') & (df_raw['Item Description'] != 'Fuel Oil #1 (Gallons)')]

In [256]:
raw_oil['Item Description'].unique()


Out[256]:
array(['FED LUS TX', 'FED OS TX', 'Misc. fee', 'Tax: Regulatory',
       'Surcharge', 'Other charges', 'HO#2', 'Service charge'], dtype=object)

In [257]:
raw_oil.query("Units != 'Gallons'")['Cost'].sum()


Out[257]:
9845.660000000027

In [258]:
raw_gas_analysis = df_raw[(df_raw['Service Name'] == 'Natural Gas') & (df_raw['Item Description'] != 'Natural gas (CCF)')]

In [259]:
raw_gas_analysis['Item Description'].unique()


Out[259]:
array(['Regulatory Cost Charge', 'Customer Charge', 'Late charge',
       'Gas Charge (CCF)', 'Other charges', 'Cost adjustments',
       'Misc. credit', 'Previous balance adj.', 'Tax: Regulatory',
       'Misc. fee', 'Service activation'], dtype=object)

In [260]:
raw_gas_analysis[raw_gas_analysis['Item Description'] == 'Misc. credit']


Out[260]:
Site ID Site Name Vendor Code Vendor Name Account Number Bill Date Due Date Entry Date Invoice # Voucher # From Thru Service Name Item Description Meter Number Usage Cost Units Account Financial Code Site Financial Code
4707 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 07/31/2012 07/31/2012 08/09/2012 NaN NaN 2012-06-30 2012-07-31 Natural Gas Misc. credit NaN NaN -4.34 NaN NaN NaN
4711 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 08/31/2012 08/31/2012 09/13/2012 NaN NaN 2012-07-31 2012-08-31 Natural Gas Misc. credit NaN NaN -4.11 NaN NaN NaN
4715 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 09/28/2012 09/28/2012 02/06/2013 NaN NaN 2012-08-31 2012-09-28 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4719 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 10/31/2012 10/31/2012 12/18/2012 NaN NaN 2012-09-28 2012-10-31 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4723 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 11/30/2012 11/30/2012 12/17/2012 NaN NaN 2012-10-31 2012-11-30 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4736 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 03/29/2013 03/29/2013 07/22/2013 NaN NaN 2013-02-28 2013-03-29 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4740 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 04/30/2013 04/30/2013 07/22/2013 NaN NaN 2013-03-29 2013-04-30 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4744 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 05/31/2013 05/31/2013 07/22/2013 NaN NaN 2013-04-30 2013-05-31 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4748 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 06/30/2013 06/30/2013 07/22/2013 NaN NaN 2013-05-31 2013-06-30 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4753 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 07/31/2013 07/31/2013 08/08/2013 NaN NaN 2013-06-30 2013-07-31 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4758 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 08/31/2013 08/31/2013 09/12/2013 NaN NaN 2013-07-31 2013-08-30 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4763 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 09/30/2013 09/30/2013 10/17/2013 NaN NaN 2013-08-30 2013-09-30 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN
4768 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 10/31/2013 10/31/2013 11/20/2013 NaN NaN 2013-09-30 2013-10-31 Natural Gas Misc. credit NaN NaN 0.00 NaN NaN NaN

In [261]:
raw_gas_analysis[raw_gas_analysis['Item Description'] == 'Cost adjustments']


Out[261]:
Site ID Site Name Vendor Code Vendor Name Account Number Bill Date Due Date Entry Date Invoice # Voucher # From Thru Service Name Item Description Meter Number Usage Cost Units Account Financial Code Site Financial Code
4496 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 10/01/2006 10/01/2006 02/24/2011 NaN NaN 2006-09-01 2006-09-29 Natural Gas Cost adjustments NaN NaN -653.8 NaN NaN NaN

In [262]:
raw_gas_analysis[raw_gas_analysis['Item Description'] == 'Previous balance adj.']


Out[262]:
Site ID Site Name Vendor Code Vendor Name Account Number Bill Date Due Date Entry Date Invoice # Voucher # From Thru Service Name Item Description Meter Number Usage Cost Units Account Financial Code Site Financial Code
4749 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 06/30/2013 06/30/2013 07/22/2013 NaN NaN 2013-05-31 2013-06-30 Natural Gas Previous balance adj. NaN NaN -25.75 NaN NaN NaN
4754 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 07/31/2013 07/31/2013 08/08/2013 NaN NaN 2013-06-30 2013-07-31 Natural Gas Previous balance adj. NaN NaN 0.00 NaN NaN NaN
4759 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 08/31/2013 08/31/2013 09/12/2013 NaN NaN 2013-07-31 2013-08-30 Natural Gas Previous balance adj. NaN NaN 0.00 NaN NaN NaN
4764 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 09/30/2013 09/30/2013 10/17/2013 NaN NaN 2013-08-30 2013-09-30 Natural Gas Previous balance adj. NaN NaN 0.00 NaN NaN NaN
4769 TRGR FNSB-Transit Garage VF314940 Fairbanks Natural Gas 10282 (3175 PEGER-TRG BG1) 10/31/2013 10/31/2013 11/20/2013 NaN NaN 2013-09-30 2013-10-31 Natural Gas Previous balance adj. NaN NaN 0.00 NaN NaN NaN

In [263]:
# Heating energy use, in MMBTUs
monthly_heating.head()


Out[263]:
service_type Natural Gas Oil #1 Steam total_heating_energy
fiscal_year fiscal_mo
2006 12 NaN NaN 0.0 0.0
2007 1 NaN NaN 0.0 0.0
2 NaN NaN 0.0 0.0
3 NaN NaN 0.0 0.0
4 NaN NaN 0.0 0.0

In [264]:
# Query the dataframe for natural gas charges with CCF only?  
df.query("service_type == 'Natural Gas'").head()


Out[264]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
180 03 Natural Gas 2006 1 Natural gas (CCF) CCF 9412.56 30.0 7394.0 2006 7 754.188
181 03 Natural Gas 2006 1 Other Charge - 45.54 30.0 NaN 2006 7 NaN
182 03 Natural Gas 2006 2 Natural gas (CCF) CCF 6684.52 27.0 5251.0 2006 8 535.602
183 03 Natural Gas 2006 2 Other Charge - 37.35 27.0 NaN 2006 8 NaN
184 03 Natural Gas 2006 3 Natural gas (CCF) CCF 3653.51 30.0 2870.0 2006 9 292.740

In [265]:
# Exclude demand charges from the natural gas costs.  This is because the unit costs for natural gas go to infinity
# when there is zero usage but a customer charge
cost_df1 = df.drop(df[(df['service_type'] == 'Natural Gas') & (df['units'] != 'CCF')].index)
cost_df1.query("service_type == 'Natural Gas'").head()


Out[265]:
site_id service_type cal_year cal_mo item_desc units cost days_served usage fiscal_year fiscal_mo mmbtu
180 03 Natural Gas 2006 1 Natural gas (CCF) CCF 9412.56 30.0 7394.0 2006 7 754.188
182 03 Natural Gas 2006 2 Natural gas (CCF) CCF 6684.52 27.0 5251.0 2006 8 535.602
184 03 Natural Gas 2006 3 Natural gas (CCF) CCF 3653.51 30.0 2870.0 2006 9 292.740
186 03 Natural Gas 2006 4 Natural gas (CCF) CCF 2599.47 29.0 2042.0 2006 10 208.284
188 03 Natural Gas 2006 5 Natural gas (CCF) CCF 1015.85 30.0 798.0 2006 11 81.396

In [266]:
# Create cost dataframe for given site from processed data
cost_df1 = cost_df1.query('site_id == @site')[['service_type', 'fiscal_year', 'fiscal_mo', 'cost']]
cost_df1.head()


Out[266]:
service_type fiscal_year fiscal_mo cost
30353 Electricity 2006 12 739.280
30354 Electricity 2006 12 0.000
30355 Electricity 2006 12 183.065
30356 Electricity 2007 1 1414.275
30357 Electricity 2007 1 0.000

In [267]:
# Split out by service type
monthly_heating_cost = pd.pivot_table(cost_df1,
                                values='cost',
                                index=['fiscal_year', 'fiscal_mo'],
                                columns=['service_type'],
                                aggfunc=np.sum
                                )
monthly_heating_cost.head()


Out[267]:
service_type Electricity Natural Gas Oil #1 Sewer Water
fiscal_year fiscal_mo
2006 12 922.345000 NaN NaN NaN NaN
2007 1 1765.355000 NaN NaN NaN NaN
2 1870.268065 NaN NaN NaN NaN
3 1459.435507 NaN NaN NaN NaN
4 1632.385461 NaN NaN 437.556613 362.837258

In [268]:
# Add in columns for the missing energy services
missing_services = bu.missing_energy_services(monthly_heating_cost.columns)
bu.add_columns(monthly_heating_cost, missing_services)

# Drop the non-heating services
monthly_heating_cost = monthly_heating_cost.drop(labels=['Electricity', 'Sewer', 'Water'], axis=1)

# Create a total heating column
monthly_heating_cost['total_heating_cost'] = monthly_heating_cost.sum(axis=1)

monthly_heating_cost.head()


Out[268]:
service_type Natural Gas Oil #1 Steam total_heating_cost
fiscal_year fiscal_mo
2006 12 NaN NaN 0.0 0.0
2007 1 NaN NaN 0.0 0.0
2 NaN NaN 0.0 0.0
3 NaN NaN 0.0 0.0
4 NaN NaN 0.0 0.0

In [269]:
monthly_heating_cost = monthly_heating_cost.rename(columns={'Natural Gas':'Natural Gas Cost',
                                                           'Oil #1':'Oil #1 Cost',
                                                           'Steam': 'Steam Cost'})
monthly_heating_cost.head()


Out[269]:
service_type Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost
fiscal_year fiscal_mo
2006 12 NaN NaN 0.0 0.0
2007 1 NaN NaN 0.0 0.0
2 NaN NaN 0.0 0.0
3 NaN NaN 0.0 0.0
4 NaN NaN 0.0 0.0

In [270]:
monthly_heat_energy_and_use = pd.merge(monthly_heating_cost, monthly_heating, left_index=True, right_index=True, how='outer')
monthly_heat_energy_and_use.head()


Out[270]:
service_type Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy
fiscal_year fiscal_mo
2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0
2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0
2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0
3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0
4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0

In [271]:
# Create unit cost columns in $ / MMBTU for each fuel type
monthly_heat_energy_and_use['fuel_oil_unit_cost'] = monthly_heat_energy_and_use['Oil #1 Cost'] / monthly_heat_energy_and_use['Oil #1']
monthly_heat_energy_and_use['natural_gas_unit_cost'] = monthly_heat_energy_and_use['Natural Gas Cost'] / monthly_heat_energy_and_use['Natural Gas']
monthly_heat_energy_and_use['district_heat_unit_cost'] = monthly_heat_energy_and_use['Steam Cost'] / monthly_heat_energy_and_use['Steam']
monthly_heat_energy_and_use['building_unit_cost'] = monthly_heat_energy_and_use.total_heating_cost / monthly_heat_energy_and_use.total_heating_energy
monthly_heat_energy_and_use.head()


Out[271]:
service_type Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_unit_cost
fiscal_year fiscal_mo
2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN
2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN
2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN
3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN
4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN

In [272]:
# Reset the index for easier processing
monthly_heat_energy_and_use = monthly_heat_energy_and_use.reset_index()

In [273]:
# Add in unit costs for fuels that are currently blank

unit_cost_cols = ['fuel_oil_unit_cost', 'natural_gas_unit_cost', 'district_heat_unit_cost']
service_types = ['Oil #1_avg_unit_cost', 'Natural Gas_avg_unit_cost', 'Steam_avg_unit_cost']

unit_cost_dict = dict(zip(unit_cost_cols,service_types))

In [274]:
# Add in average unit costs calculated from all sites for each month
monthly_heat_energy_and_use = pd.merge(monthly_heat_energy_and_use, grouped_nonzero_heatfuel_use, 
                                       left_on=['fiscal_year', 'fiscal_mo'], right_on=['fiscal_year', 'fiscal_mo'],
                                      how='left', suffixes=('', '_avg_unit_cost'))
monthly_heat_energy_and_use.head()


Out[274]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_unit_cost Natural Gas_avg_unit_cost Oil #1_avg_unit_cost Steam_avg_unit_cost
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN 12.512925 17.000551 6.219821
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN 13.725490 13.708584 4.803764
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN 13.689365 16.168198 8.501139
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN 12.494336 14.966004 9.015808
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 NaN NaN NaN NaN 13.725490 14.520701 9.843281

In [275]:
# Check each column to see if it is NaN (identified when the value does not equal itself) and if it is, fill with the average
# price per MMBTU taken from all sites
for col, service in unit_cost_dict.items():
    monthly_heat_energy_and_use[col] = np.where(monthly_heat_energy_and_use[col] != monthly_heat_energy_and_use[col],
                                               monthly_heat_energy_and_use[service], 
                                               monthly_heat_energy_and_use[col])

In [276]:
def fiscal_to_calendar(fiscal_year, fiscal_mo):
    """Converts a fiscal year and month into a calendar year and month for graphing purposes.
    Returns (calendar_year, calendar_month) tuple."""
    
    if fiscal_mo > 6:
        calendar_month = fiscal_mo - 6
        calendar_year = fiscal_year
    else:
        calendar_month = fiscal_mo + 6
        calendar_year = fiscal_year - 1
        
    return (calendar_year, calendar_month)

In [277]:
# Add calendar year and month columns
cal_year = []
cal_mo = []
for fiscal_year, fiscal_mo in zip(monthly_heat_energy_and_use.fiscal_year, monthly_heat_energy_and_use.fiscal_mo):
    CalYear, CalMo = fiscal_to_calendar(fiscal_year, fiscal_mo)
    cal_year.append(CalYear)
    cal_mo.append(CalMo)
monthly_heat_energy_and_use['calendar_year'] = cal_year
monthly_heat_energy_and_use['calendar_mo'] = cal_mo
monthly_heat_energy_and_use.head()


Out[277]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_unit_cost Natural Gas_avg_unit_cost Oil #1_avg_unit_cost Steam_avg_unit_cost calendar_year calendar_mo
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 17.000551 12.512925 6.219821 NaN 12.512925 17.000551 6.219821 2006 6
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 13.708584 13.725490 4.803764 NaN 13.725490 13.708584 4.803764 2006 7
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 16.168198 13.689365 8.501139 NaN 13.689365 16.168198 8.501139 2006 8
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 14.966004 12.494336 9.015808 NaN 12.494336 14.966004 9.015808 2006 9
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 14.520701 13.725490 9.843281 NaN 13.725490 14.520701 9.843281 2006 10

In [278]:
# Create a date column using the calendar year and month to pass to the graphing function

def get_date(row):
    return datetime.date(year=row['calendar_year'], month=row['calendar_mo'], day=1)

monthly_heat_energy_and_use['date'] = monthly_heat_energy_and_use[['calendar_year','calendar_mo']].apply(get_date, axis=1)
monthly_heat_energy_and_use.head()


Out[278]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_unit_cost Natural Gas_avg_unit_cost Oil #1_avg_unit_cost Steam_avg_unit_cost calendar_year calendar_mo date
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 17.000551 12.512925 6.219821 NaN 12.512925 17.000551 6.219821 2006 6 2006-06-01
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 13.708584 13.725490 4.803764 NaN 13.725490 13.708584 4.803764 2006 7 2006-07-01
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 16.168198 13.689365 8.501139 NaN 13.689365 16.168198 8.501139 2006 8 2006-08-01
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 14.966004 12.494336 9.015808 NaN 12.494336 14.966004 9.015808 2006 9 2006-09-01
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 14.520701 13.725490 9.843281 NaN 13.725490 14.520701 9.843281 2006 10 2006-10-01

In [289]:
%matplotlib inline

In [290]:
p9g1_filename, p9g1_url = gu.graph_filename_url(site, "energy_cost")
gu.fuel_price_comparison_graph(monthly_heat_energy_and_use, 'date', unit_cost_cols, 'building_unit_cost', p9g1_filename)

Realized Savings from Fuel Switching: Page 9, Graph 2


In [280]:
monthly_heat_energy_and_use.head()


Out[280]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy fuel_oil_unit_cost natural_gas_unit_cost district_heat_unit_cost building_unit_cost Natural Gas_avg_unit_cost Oil #1_avg_unit_cost Steam_avg_unit_cost calendar_year calendar_mo date
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 17.000551 12.512925 6.219821 NaN 12.512925 17.000551 6.219821 2006 6 2006-06-01
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 13.708584 13.725490 4.803764 NaN 13.725490 13.708584 4.803764 2006 7 2006-07-01
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 16.168198 13.689365 8.501139 NaN 13.689365 16.168198 8.501139 2006 8 2006-08-01
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 14.966004 12.494336 9.015808 NaN 12.494336 14.966004 9.015808 2006 9 2006-09-01
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 14.520701 13.725490 9.843281 NaN 13.725490 14.520701 9.843281 2006 10 2006-10-01

In [281]:
old_usage_cols = ['Natural Gas', 'Oil #1', 'Steam']

In [282]:
# Create an indicator for whether a given heating fuel is available for the facility.  This is done by checking the use for all
# months- if it is zero, then that building doesn't have the option to use that type of fuel.



for col in old_usage_cols:
    new_col_name = col + "_available"
    monthly_heat_energy_and_use[new_col_name] = np.where(monthly_heat_energy_and_use[col].sum() == 0, 0, 1)

monthly_heat_energy_and_use.head()


Out[282]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy ... building_unit_cost Natural Gas_avg_unit_cost Oil #1_avg_unit_cost Steam_avg_unit_cost calendar_year calendar_mo date Natural Gas_available Oil #1_available Steam_available
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... NaN 12.512925 17.000551 6.219821 2006 6 2006-06-01 1 1 0
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... NaN 13.725490 13.708584 4.803764 2006 7 2006-07-01 1 1 0
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... NaN 13.689365 16.168198 8.501139 2006 8 2006-08-01 1 1 0
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... NaN 12.494336 14.966004 9.015808 2006 9 2006-09-01 1 1 0
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... NaN 13.725490 14.520701 9.843281 2006 10 2006-10-01 1 1 0

5 rows × 23 columns


In [283]:
# Calculate what it would have cost if the building used only one fuel type

available_cols = ['Oil #1_available','Natural Gas_available','Steam_available']
available_dict = dict(zip(unit_cost_cols, available_cols))
print (available_dict)
hypothetical_cost_cols = []

for unit_cost, avail_col in available_dict.items():
    new_col_name = unit_cost + "_hypothetical"
    hypothetical_cost_cols.append(new_col_name)
    monthly_heat_energy_and_use[new_col_name] = monthly_heat_energy_and_use[unit_cost] * \
    monthly_heat_energy_and_use.total_heating_energy * monthly_heat_energy_and_use[avail_col]
    
monthly_heat_energy_and_use.head()


{'natural_gas_unit_cost': 'Natural Gas_available', 'district_heat_unit_cost': 'Steam_available', 'fuel_oil_unit_cost': 'Oil #1_available'}
Out[283]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy ... Steam_avg_unit_cost calendar_year calendar_mo date Natural Gas_available Oil #1_available Steam_available natural_gas_unit_cost_hypothetical district_heat_unit_cost_hypothetical fuel_oil_unit_cost_hypothetical
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 6.219821 2006 6 2006-06-01 1 1 0 0.0 0.0 0.0
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 4.803764 2006 7 2006-07-01 1 1 0 0.0 0.0 0.0
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 8.501139 2006 8 2006-08-01 1 1 0 0.0 0.0 0.0
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 9.015808 2006 9 2006-09-01 1 1 0 0.0 0.0 0.0
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 9.843281 2006 10 2006-10-01 1 1 0 0.0 0.0 0.0

5 rows × 26 columns


In [284]:
# Calculate the monthly savings to the building by not using the most expensive available fuel entirely
monthly_heat_energy_and_use['fuel_switching_savings'] = monthly_heat_energy_and_use[hypothetical_cost_cols].max(axis=1) \
                                                        - monthly_heat_energy_and_use.total_heating_cost

In [285]:
# Sort dataframe to calculate cumulative value
monthly_heat_energy_and_use = monthly_heat_energy_and_use.sort_values(by='date', ascending=True)

# Calculate cumulative value
monthly_heat_energy_and_use['cumulative_fuel_switching_savings'] = np.cumsum(monthly_heat_energy_and_use.fuel_switching_savings)

monthly_heat_energy_and_use.head()


Out[285]:
service_type fiscal_year fiscal_mo Natural Gas Cost Oil #1 Cost Steam Cost total_heating_cost Natural Gas Oil #1 Steam total_heating_energy ... calendar_mo date Natural Gas_available Oil #1_available Steam_available natural_gas_unit_cost_hypothetical district_heat_unit_cost_hypothetical fuel_oil_unit_cost_hypothetical fuel_switching_savings cumulative_fuel_switching_savings
0 2006 12 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 6 2006-06-01 1 1 0 0.0 0.0 0.0 0.0 0.0
1 2007 1 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 7 2006-07-01 1 1 0 0.0 0.0 0.0 0.0 0.0
2 2007 2 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 8 2006-08-01 1 1 0 0.0 0.0 0.0 0.0 0.0
3 2007 3 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 9 2006-09-01 1 1 0 0.0 0.0 0.0 0.0 0.0
4 2007 4 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 ... 10 2006-10-01 1 1 0 0.0 0.0 0.0 0.0 0.0

5 rows × 28 columns


In [286]:
p9g2_filename, p9g2_url = gu.graph_filename_url(site, "cumulative_fuel_switching_savings")
gu.create_monthly_line_graph(monthly_heat_energy_and_use, 'date', 'cumulative_fuel_switching_savings',
                            'Cumulative Fuel Switching Savings Realized [$]', p9g2_filename)

In [287]:
# Convert df to dictionary
heating_cost_rows = bu.df_to_dictionaries(heating_cost_and_use)

# Add data and graphs to main dictionary
template_data['heating_cost_analysis'] = dict(
    graphs=[p9g1_url, p9g2_url],
    table={'rows': heating_cost_rows},
)

Water Analysis Table - Page 10


In [ ]:
water_use = df.query('site_id == @site')[['service_type', 'fiscal_year', 'fiscal_mo','cost', 'usage', 'units']]
water_use.head()

In [ ]:
# Create month count field for all months that have water and sewer bills
water_use_only = water_use.query("service_type == 'Water'")
water_months_present = bu.months_present(water_use_only)
water_mo_count = bu.month_count(water_months_present)
water_mo_count

In [ ]:
# Create annual water gallon usage dataframe
water_gal_df = pd.pivot_table(water_use, 
                              values='usage',
                              index=['fiscal_year',], 
                              columns=['service_type'],
                              aggfunc=np.sum
)

water_gal_df.head()

In [ ]:
# Use only required columns 
water_gal_df = water_gal_df[['Water']]
# Calculate percent change column
water_gal_df['water_use_pct_change'] = water_gal_df.Water.pct_change()

In [ ]:


In [ ]:
# Create annual water and sewer cost dataframe
water_cost_df = pd.pivot_table(water_use, 
                              values='cost',
                              index=['fiscal_year',], 
                              columns=['service_type'],
                              aggfunc=np.sum
)

water_cost_df.head()

In [ ]:
# Calculate totals, percent change
    water_cost_df = water_cost_df[water_cost_df.columns.difference(['Electricity', 'Natural Gas', 'Oil #1', 'Steam', 'Refuse'])]
    
    # Rename columns only if they exist in the water cost dataframe
    rename_dict = {'Sewer': 'Sewer Cost',
                   'Water': 'Water Cost'}
    water_cost_df = water_cost_df.rename(columns={k: v for k, v in rename_dict.items() if k in water_cost_df})
    
    # First check to make sure sewer data is included; if so, calculate total cost
    water_cost_df['total_water_sewer_cost'] = np.where('Sewer Cost' in list(water_cost_df.columns.values),
                                                       water_cost_df['Sewer Cost'] + water_cost_df['Water Cost'],
                                                       water_cost_df['Water Cost'])

In [ ]:
water_cost_df['water_cost_pct_change'] = water_cost_df['Water Cost'].pct_change()
                                                       
    # First check to make sure sewer data is included; if so, calculate percent change
    water_cost_df['sewer_cost_pct_change'] = np.where('Sewer Cost' in list(water_cost_df.columns.values),
                                                      water_cost_df['Sewer Cost'].pct_change(),
                                                      np.nan)
                                                       
    water_cost_df['total_water_sewer_cost_pct_change'] = water_cost_df.total_water_sewer_cost.pct_change()

In [ ]:


In [ ]:
# Merge use and cost dataframes
water_use_and_cost = pd.merge(water_cost_df, water_gal_df, left_index=True, right_index=True, how='outer')
water_use_and_cost.head()

In [ ]:
water_use_and_cost['water_unit_cost'] = water_use_and_cost.total_water_sewer_cost / water_use_and_cost.Water
water_use_and_cost['water_unit_cost_pct_change'] = water_use_and_cost.water_unit_cost.pct_change()

# Use only complete years 
water_use_and_cost['month_count'] = water_mo_count
water_use_and_cost = water_use_and_cost.query("month_count == 12")
water_use_and_cost = water_use_and_cost.drop('month_count', axis=1)
water_use_and_cost = water_use_and_cost.sort_index(ascending=False)
water_use_and_cost = water_use_and_cost.rename(columns={'Sewer Cost':'sewer_cost',
                                                       'Water Cost':'water_cost',
                                                       'total_water_sewer_cost':'total_cost',
                                                       'total_water_sewer_cost_pct_change':'total_cost_pct_change',
                                                       'Water':'total_usage',
                                                       'water_usage_pct_change':'total_usage_pct_change',
                                                       'water_unit_cost':'total_unit_cost',
                                                       'water_unit_cost_pct_change':'total_unit_cost_pct_change'
                                                       })
water_use_and_cost

Create Water Cost Stacked Bar Graph - Page 10 Graph 1


In [ ]:
p10g1_filename, p10g1_url = gu.graph_filename_url(site, "utility_cost")
gu.create_stacked_bar(water_use_and_cost.reset_index(), 'fiscal_year', ['sewer_cost', 'water_cost'], 
                      'Utility Cost [$]', "test title", p10g1_filename)

Create Monthly Profile of Water Usage - Page 10 Graph 2


In [ ]:
# Create monthly water gallon dataframe
water_gal_df_monthly = pd.pivot_table(water_use, 
                              values='usage',
                              index=['fiscal_year', 'fiscal_mo'], 
                              columns=['service_type'],
                              aggfunc=np.sum
)

water_gal_df_monthly.head()

In [ ]:
p10g2_filename, p10g2_url = gu.graph_filename_url(site, "monthly_water_usage_profile")
gu.create_monthly_profile(water_gal_df_monthly, 'Water', 'Monthly Water Usage Profile [gallons]', 'green', p10g2_filename)

In [ ]:
# Convert df to dictionary
water_rows = bu.df_to_dictionaries(water_use_and_cost)

# Add data and graphs to main dictionary
template_data['water_analysis'] = dict(
    graphs=[p10g1_url, p10g2_url],
    table={'rows': water_rows},
)

In [ ]:
template_data