Building Energy Boot Camp 2018 - Day 3

Today we learned the difference between energy waste and energy loss. Energy waste is when someone or something uses energy in a way that could’ve been prevented, like leaving the lights on when you leave the room. Energy loss is when energy is turned into heat or another form and is lost. Afterwards, the town’s director of facilities came into our room and taught us how the town gets its energy from solar plants. We also learned about net metering, and how it can help you balance your solar electricity use. From her lesson, we learned that Andover High School is just about 100% solar powered, something we were never told.

Palmer Solar Plant

The solar plant at the Palmer Landfill, where the town gets its solar energy


Today, we also revisited our program from last time, HighCO2.py (See Day 2). Upon further examination of our data file, we realized that it included both weekdays and weekends.

CSV data

The data in our CSV. Notice that January 13th was a Saturday and the 14th was a Sunday


As there is no school on Saturday or Sunday, our programs should’ve ignored them, as the extra data skewed our results. To fix this, we learned about working with https://docs.python.org/2/library/datetime.html in https://pandas.pydata.org/, and I combined this new knowledge with pandas filtering to update the file like so:

import pandas as pd

FILE = '2018 Q1Q2 - AHS CO2 (0800-1530).csv'

high_co2_rooms = []


def print_results():
    print("Now listing the %s rooms with average CO2 levels above 1000 ppm:\n" % len(high_co2_rooms))

    for room in high_co2_rooms:
        print(room[0] + '   -   ' + room[1])


try:
    df = pd.read_csv(FILE)

    df['Unnamed: 0'] = pd.to_datetime(df['Unnamed: 0'], format='%m/%d/%Y %H:%M')
    df = df[df['Unnamed: 0'].dt.weekday < 5]

    firstCol = True

    for series in df:
        series = df[series]
        if firstCol:
            firstCol = False
            continue

        if series.mean() > 1000:
            high_co2_rooms.append([series.name, str("%.2f ppm" % series.mean())])

    print_results()

except KeyboardInterrupt:
    print_results()

Running this script gave me the following output:

Now listing the 16 rooms with average CO2 levels above 1000 ppm:

RM305 ZN14 CO2   -   1186.28 ppm
RM227 ZN21 Q CO2   -   1011.57 ppm
RM307 ZN14 Q CO2   -   1220.97 ppm
RM335 ZN18 CO2   -   1420.70 ppm
RM337 ZN18 CO2   -   1119.39 ppm
RM339 ZN18 CO2   -   1118.02 ppm
RM341 ZN18 CO2   -   1282.47 ppm
RM343 ZN18 CO2   -   1426.01 ppm
RM264A ZN02 CO2   -   1416.94 ppm
RM357 ZN20 CO2   -   1186.21 ppm
RM370 ZN20 CO2   -   1110.52 ppm
RM345 ZN20 CO2   -   1310.89 ppm
RM349 ZN20 CO2   -   1225.83 ppm
RM203 ZN19 CO2   -   1032.80 ppm
RM323 ZN22 CO2   -   1010.86 ppm
RM326 ZN22 CO2   -   1008.43 ppm

By examining this data, I came to the conclusion that zones 18 - 20 have a big CO2 problem. This may be due to a lack of ventilation, or it may be linked to the third floor in general. Further investigation will be required to learn more.

After this, I was tasked with finding all the classrooms which, during school hours, in the month of June specifically, had an average temperature of at least 75 degrees Fahrenheit. June is the hottest month of our school year, and many rooms, especially on the third floor, can often feel way too hot, so this script helps point out the particularly hot rooms:

import pandas as pd

FILE = '2018 Q1Q2 - AHS Temperature.csv'

high_temp_rooms = []

df = pd.read_csv(FILE, skipfooter=3, engine='python')
df['Unnamed: 0'] = pd.to_datetime(df['Unnamed: 0'], format='%Y-%m-%d %H:%M:%S')

df = df[(df['Unnamed: 0'].dt.month == 6) & (df['Unnamed: 0'].dt.weekday < 5) & (df['Unnamed: 0'].dt.hour >= 8) & (
        df['Unnamed: 0'].dt.hour <= 15)]

avgTemps = df.mean()
avgTemps = avgTemps[avgTemps > 75]

print('There are ' + str(len(avgTemps)) + ' rooms with a temperature problem: \n\n')
print(avgTemps)

Running this script gave me the following list of 55 different rooms!​ That’s a lot of hot rooms!

There are 55 rooms with a temperature problem: 


RM253 ZN20 ZN-T         78.527405
RM355 ZN14 ZN-T         75.072592
AHU13 Boiler ZN-T       76.416310
AHU14 ZN01 ZN-T         76.674735
AHU12 ZN02  ZN-T        75.787544
RM361 ZN20 ZN-T         76.741948
AHU11 ZN03 ZN-T         75.327773
Dunn Gym ZN-T           76.643429
RM260 ZN11 ZN-T        104.930326
RM303  ZN-T             77.720279
RM305  ZN-T             77.310061
RM307  ZN-T             77.584827
RM309  ZN-T             77.335854
RM311  ZN-T             78.151562
RM313  ZN-T             78.040720
RM335 ZN18 ZN-T         77.457249
RM337  ZN-T             77.478939
RM339  ZN-T             76.646829
RM341  ZN-T             77.458364
RM343 ZN18 ZN-T         76.713024
RM349 ZN20 ZN-T         76.187894
RM379 ZN18 ZN-T         75.011971
RM201  ZN-              77.413425
RM203  ZN-T             77.709135
RM205  ZN-T             78.645178
RM207  ZN-T             78.653854
RM264A  ZN-T            75.694749
RM264B  ZN-T            76.262233
RM301  ZN-T             76.598974
RM320 ZN22 ZN-T         77.697205
RM323  ZN-T             76.862201
RM325  ZN-              76.427706
RM326  ZN-T             77.931754
RM328  ZN-T             78.503132
RM345 ZN18 ZN-T         76.703323
RM347 ZN20 ZN-T         76.408396
RM351  ZN-T             75.781718
RM357 ZN20 ZN-T         78.514196
RM359 ZN20 ZN-T         77.928459
RM363  ZN-T             78.123355
RM367 ZN-T              76.918004
RM370 ZN20 ZN-T         77.148937
RM381 ZN18 ZN-T         75.344224
CAFE-UV UV08 ZN-T       78.043563
CAFE-UV01 UV1 ZN-T      77.484682
CAFE-UV14 UV14 ZN-T     78.043563
CAFE-UV02 UV2 ZN-T      77.484682
RM251  ZN-T             75.309724
RM215 ZN-T              76.730361
RM224  ZN-T             75.772388
RM226  ZN-T             75.094666
RM243  ZN-T             75.077964
RM271  ZN-T             75.266445
RM255B ZN15 ZN-T        75.160715
RM209 ZN19 ZN-T         75.996254

Finally, I wrote a script that analyzed the electricity used by the Collins Center throughout the years 2016 and 2017, and outputted all sorts of comparisons and statistics:

import pandas as pd

NIGHT_PATH_2016 = '2016 Q1Q4 - Electrical Nightly (2300-0400).csv'
PATH_2016 = '2016 Q1Q4 - Electrical(24 Hrs).csv'
NIGHT_PATH_2017 = '2017 Q1Q4 - Electrical Energy & Gas Nightly (2300 - 0400).csv'
PATH_2017 = '2017 Q1Q4 - Electrical Energy (24 hrs).csv'

MAIN_COL = 'HS Main (kWh)'
CC_COL = 'HS CC (kWh)'

PRICE_PER_KWH = 0.16

COLS_TO_USE = [MAIN_COL, CC_COL]


def read_csv(path):
    return pd.read_csv(path, skiprows=[0], skipfooter=3, engine='python', usecols=COLS_TO_USE)


def night_vs_day(year, elec_night, elec):
    print('In the year ' + str(year) + ', the Collins Center used:\nAbout ' + str(
        round(elec, 2)) + ' kWh of energy a day\nAbout ' + str(
        round(elec_night, 2)) + ' kWh of energy between 11:00PM and' + ' 4:00AM\nAbout ' + str(
        round(elec - elec_night, 2)) + ' more kWh of energy throughout the entire day than at night\n')


def year_result(big_year, big_val, small_year, small_val, night):
    if night:
        print('In the year ' + str(big_year) + ' the Collins Center used about ' + str(round(
            big_val - small_val, 2)) + ' kWh more energy at night than in the year ' + str(small_year))
    else:
        print('In the year ' + str(big_year) + ' the Collins Center used about ' + str(round(
            big_val - small_val, 2)) + ' kWh more energy throughout the day than in the year ' + str(small_year))


def year_vs_year(year1, elec_night1, elec1, year2, elec_night2, elec2):
    if elec1 > elec2:
        year_result(year1, elec1, year2, elec2, False)
    else:
        year_result(year2, elec2, year1, elec1, False)
    if elec_night1 > elec_night2:
        year_result(year1, elec1, year2, elec2, True)
    else:
        year_result(year2, elec2, year1, elec1, True)


def price_result(big_year, big_val, small_year, small_val, night):
    if night:
        print('In the year ' + str(big_year) + ' the Collins Center\'s energy cost about $' + str(
            round(big_val, 2)) + ', about $' + str(round(big_val - small_val, 2)) + ' more than in the year ' + str(
            small_year) + ', which cost about $' + str(round(small_val, 2)) + ', at night')
    else:
        print('In the year ' + str(big_year) + ' the Collins Center\'s energy cost about $' + str(
            round(big_val, 2)) + ', about $' + str(round(big_val - small_val, 2)) + ' more than in the year ' + str(
            small_year) + ', which cost about $' + str(round(small_val, 2)) + ', throughout the day')


def compare_price(year1, elec1, year2, elec2, night):
    if elec1 > elec2:
        price_result(year1, elec1, year2, elec2, night)
    else:
        price_result(year2, elec2, year1, elec1, night)


def part_of_main(year, elec, main):
    print('In the year ' + str(year) + ', the Collins Center used ' + str(
        round(elec, 2)) + ' kWh in total out of the ' + str(round(main, 2)) + ' kWh that the school used in total')


def percent_of_main(year, elec, main):
    percent = elec * 100 / main
    print(("In the year {0}, the Collins Center used ${1} of energy in total, {2}\u0025 of the total cost of " +
           "energy in AHS, ${3}").format(year, round(elec, 2), round(percent, 2), round(main, 2)))


##################2016##################
df_night_2016 = read_csv(NIGHT_PATH_2016)
df_2016 = read_csv(PATH_2016)

electricity_night_cc_2016 = df_night_2016[CC_COL].sum()
electricity_cc_2016 = df_2016[CC_COL].sum()

ahs_electricity_2016 = df_2016[MAIN_COL].sum()

night_price_cc_2016 = electricity_night_cc_2016 * PRICE_PER_KWH
price_cc_2016 = electricity_cc_2016 * PRICE_PER_KWH

price_ahs_2016 = ahs_electricity_2016 * PRICE_PER_KWH

##################2017##################
df_night_2017 = read_csv(NIGHT_PATH_2017)
df_2017 = read_csv(PATH_2017)

electricity_night_cc_2017 = df_night_2017[CC_COL].sum()
electricity_cc_2017 = df_2017[CC_COL].sum()

ahs_electricity_2017 = df_2017[MAIN_COL].sum()

night_price_cc_2017 = electricity_night_cc_2017 * PRICE_PER_KWH
price_cc_2017 = electricity_cc_2017 * PRICE_PER_KWH

price_ahs_2017 = ahs_electricity_2017 * PRICE_PER_KWH

##################RESULTS##################
night_vs_day(2016, electricity_night_cc_2016, electricity_cc_2016)
night_vs_day(2017, electricity_night_cc_2017, electricity_cc_2017)

year_vs_year(2016, electricity_night_cc_2016, electricity_cc_2016, 2017, electricity_night_cc_2017, electricity_cc_2017)

print('\n')

compare_price(2016, night_price_cc_2016, 2017, night_price_cc_2017, True)
compare_price(2016, price_cc_2016, 2017, price_cc_2017, False)

print('\n')

part_of_main(2016, electricity_cc_2017, ahs_electricity_2017)

print('\n')

percent_of_main(2016, price_cc_2016, price_ahs_2016)
percent_of_main(2017, price_cc_2017, price_ahs_2017)

Running this script gave the following output:

In the year 2016, the Collins Center used:
About 309461.5 kWh of energy a day
About 32725.6 kWh of energy between 11:00PM and 4:00AM
About 276735.9 more kWh of energy throughout the entire day than at night

In the year 2017, the Collins Center used:
About 276071.9 kWh of energy a day
About 30242.2 kWh of energy between 11:00PM and 4:00AM
About 245829.7 more kWh of energy throughout the entire day than at night

In the year 2016 the Collins Center used about 33389.6 kWh more energy throughout the day than in the year 2017
In the year 2016 the Collins Center used about 33389.6 kWh more energy at night than in the year 2017


In the year 2016 the Collins Center's energy cost about $5236.1, about $397.34 more than in the year 2017, which cost about $4838.75, at night
In the year 2016 the Collins Center's energy cost about $49513.84, about $5342.34 more than in the year 2017, which cost about $44171.5, throughout the day


In the year 2016, the Collins Center used 276071.9 kWh in total out of the 1573257.0 kWh that the school used in total


In the year 2016, the Collins Center used $49513.84 of energy in total, 18.14% of the total cost of energy in AHS, $272879.68
In the year 2017, the Collins Center used $44171.5 of energy in total, 17.55% of the total cost of energy in AHS, $251721.12

Unfortunately, I will miss the next 3 meetings, as I am going away for the long weekend. I will attempt to continue my work remotely and document my progress here, but be warned - I will definitely have less information and/or scripts.