From ff4bb6eb9cb4271b87b594aaf463e012516c3722 Mon Sep 17 00:00:00 2001 From: Boya Yu Date: Thu, 27 Apr 2017 12:13:07 -0400 Subject: [PATCH 1/5] Fix a bug that sometimes leads to negative outputs --- bpeng/bill/disaggregate.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bpeng/bill/disaggregate.py b/bpeng/bill/disaggregate.py index d0587a4..0a6c9ba 100644 --- a/bpeng/bill/disaggregate.py +++ b/bpeng/bill/disaggregate.py @@ -95,16 +95,14 @@ class BillDisaggregation(): """HDD (for each day)""" if curr_temp > set_temp: return 0 - else: - return set_temp - curr_temp + return set_temp - curr_temp @staticmethod def cooling(curr_temp, set_temp): """ CDD (for each day) """ if curr_temp > set_temp: return curr_temp - set_temp - else: - return 0 + return 0 @staticmethod def regression_r2_op(set_heating, set_cooling, temperature, consumption): @@ -215,6 +213,12 @@ class BillDisaggregation(): self.cooling_load_m = self.cooling_load_m * sum_ratio self.others_m = self.others_m * sum_ratio + if sum(self.others_m < 0) > 0: + self.heating_load_m, self.cooling_load_m = \ + np.array([self.heating_load_m, self.cooling_load_m]) \ + * real_sum / (self.cooling_load_m + self.heating_load_m) + self.others_m = np.zeros(len(self.others_m)) + # For printing output bill_cp = self.bill.copy() bill_cp = bill_cp[['Bill From Date', 'Bill To Date', 'Days In Bill', 'Usage']] -- GitLab From 21129e6605eb590ddd904472af1567b93b8ea32d Mon Sep 17 00:00:00 2001 From: Boya Yu Date: Mon, 1 May 2017 13:50:16 -0400 Subject: [PATCH 2/5] Minor changes --- bpeng/bill/disaggregate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bpeng/bill/disaggregate.py b/bpeng/bill/disaggregate.py index 0a6c9ba..e8849ca 100644 --- a/bpeng/bill/disaggregate.py +++ b/bpeng/bill/disaggregate.py @@ -213,7 +213,7 @@ class BillDisaggregation(): self.cooling_load_m = self.cooling_load_m * sum_ratio self.others_m = self.others_m * sum_ratio - if sum(self.others_m < 0) > 0: + if any(i < 0 for i in self.others_m): self.heating_load_m, self.cooling_load_m = \ np.array([self.heating_load_m, self.cooling_load_m]) \ * real_sum / (self.cooling_load_m + self.heating_load_m) -- GitLab From 54ff642ff7a38aebed40276e7be45a53e93e7fa6 Mon Sep 17 00:00:00 2001 From: Boya Yu Date: Tue, 2 May 2017 16:16:24 -0400 Subject: [PATCH 3/5] 'Add choice of monthly output' --- bpeng/bill/disaggregate.py | 67 +++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/bpeng/bill/disaggregate.py b/bpeng/bill/disaggregate.py index e8849ca..6ca7c89 100644 --- a/bpeng/bill/disaggregate.py +++ b/bpeng/bill/disaggregate.py @@ -1,12 +1,12 @@ """ This file will be used for calculate bill disaggregation """ +from datetime import timedelta import pandas as pd import numpy as np from sklearn import linear_model from scipy.optimize import minimize - class BillDisaggregation(): """ Class for Bill Disaggregation @@ -40,6 +40,7 @@ class BillDisaggregation(): self.set_point = None self.days_in_12_bills = None self.output_table = None + self.output_monthly = None def weather_period(self, period_end_date, days_in_period): """ @@ -58,7 +59,7 @@ class BillDisaggregation(): # end_datetime = period_end_date.date().strftime("%/%m/%d") end_datetime = '/'.join([str(period_end_date.date().month), str(period_end_date.date().day), - str(period_end_date.date().year)]) + str(period_end_date.date().year)[2:]]) end_date_id = self.daily_temp[self.daily_temp.date == end_datetime].index[0] start_date_id = end_date_id - int(days_in_period) return list(self.daily_temp['temperature'][start_date_id:end_date_id]) @@ -233,10 +234,56 @@ class BillDisaggregation(): self.set_point = opt.x[0] self.days_in_12_bills = sum(days[:12]) self.output_table = bill_cp + self.output_monthly = BillDisaggregation.output_to_monthly(self.output_table) else: print('Low R-squared') + @staticmethod + def output_to_monthly(output): + """ + Transfrom period-wise output to month-wise output + + Args: + + output (pd.DataFrame): a pandas dataframe like `self.output_table` + + Returns: + + pd.DataFrame: result with monthly consumptions + + """ + last_date = pd.to_datetime(output['Bill To Date']).iloc[0] + days_in_recent_year = 365 + if (last_date - timedelta(365)).day != last_date.day: + days_in_recent_year = 366 + days_cumsum = np.array(output['Days In Bill']).cumsum() + periods_in_recent_year = \ + next(i for i, v in enumerate(days_cumsum) if v >= days_in_recent_year) + bill_in_recent_year = output.iloc[:(periods_in_recent_year + 1)] + values_in_recent_year = bill_in_recent_year.iloc[:, 2:].values + values_in_recent_year[-1] *= \ + 1 - (days_cumsum[periods_in_recent_year] - days_in_recent_year) \ + / values_in_recent_year[-1][0] + daily_usage = \ + np.concatenate([np.tile(i[1:] / i[0], (int(i[0]), 1)) \ + for i in values_in_recent_year])[::-1] + day_of_year = last_date.timetuple().tm_yday - 1 + daily_usage = np.roll(daily_usage, day_of_year, axis=0) + month_days = [31, 28, 31, 30, 31, 30, \ + 31, 31, 30, 31, 30, 31] + if days_in_recent_year == 366: + month_days[1] = 29 + month_cumsum = np.insert(np.cumsum(month_days), 0, 0) + output_monthly = \ + pd.DataFrame([daily_usage[month_cumsum[i]:month_cumsum[i+1]]\ + .sum(axis=0) for i in range(12)]) + output_monthly.columns = [output.columns[3:]] + output_monthly['Month'] = range(1, 13) + output_monthly = output_monthly.iloc[:, [4, 0, 1, 2, 3]] + return output_monthly + + def output(self): """ Output in csv file @@ -244,12 +291,24 @@ class BillDisaggregation(): """ return self.output_table.to_csv(None) - def to_json(self): + def to_json(self, period='month'): """ Output in json file + Args: + + period (str): 'month' for monthly + 'bill' for each bill period + default 'month' + + Returns: + + json: output in json format + """ - return self.output_table.to_json(orient="records") + if period == 'bill': + return self.output_table.to_json(orient="records") + return self.output_monthly.to_json(orient="records") def print_all_features(self): """ -- GitLab From 0cd5731f71dd4e9638ac65a6b05af34ccdd368b9 Mon Sep 17 00:00:00 2001 From: Boya Yu Date: Tue, 2 May 2017 16:25:44 -0400 Subject: [PATCH 4/5] Minor changes --- bpeng/bill/disaggregate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bpeng/bill/disaggregate.py b/bpeng/bill/disaggregate.py index 6ca7c89..8b7fc83 100644 --- a/bpeng/bill/disaggregate.py +++ b/bpeng/bill/disaggregate.py @@ -59,7 +59,7 @@ class BillDisaggregation(): # end_datetime = period_end_date.date().strftime("%/%m/%d") end_datetime = '/'.join([str(period_end_date.date().month), str(period_end_date.date().day), - str(period_end_date.date().year)[2:]]) + str(period_end_date.date().year)]) end_date_id = self.daily_temp[self.daily_temp.date == end_datetime].index[0] start_date_id = end_date_id - int(days_in_period) return list(self.daily_temp['temperature'][start_date_id:end_date_id]) -- GitLab From 7ce00969599ffd95a7c094b9f202f7131f232d2c Mon Sep 17 00:00:00 2001 From: Boya Yu Date: Tue, 2 May 2017 16:56:22 -0400 Subject: [PATCH 5/5] 'Change default json output type, add detail requirements to the `output_to_monthly` static method' --- bpeng/bill/disaggregate.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bpeng/bill/disaggregate.py b/bpeng/bill/disaggregate.py index 8b7fc83..fbe7512 100644 --- a/bpeng/bill/disaggregate.py +++ b/bpeng/bill/disaggregate.py @@ -247,6 +247,10 @@ class BillDisaggregation(): Args: output (pd.DataFrame): a pandas dataframe like `self.output_table` + columns of the dataframe must be (in order): + 'Bill From Date', 'Bill To Date', + 'Days In Bill', 'Usage', 'Heating Usage', + 'Cooling Usage', 'Other Usage' Returns: @@ -291,7 +295,7 @@ class BillDisaggregation(): """ return self.output_table.to_csv(None) - def to_json(self, period='month'): + def to_json(self, period='bill'): """ Output in json file @@ -299,7 +303,7 @@ class BillDisaggregation(): period (str): 'month' for monthly 'bill' for each bill period - default 'month' + default 'bill' Returns: -- GitLab