diff --git a/bpeng/bill/disaggregate.py b/bpeng/bill/disaggregate.py index e8849ca4ba201ebcd6006ae544da0c7550143a1e..fbe751208318b81a9b31b14c78e25cf491417c45 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): """ @@ -233,10 +234,60 @@ 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` + 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: + + 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 +295,24 @@ class BillDisaggregation(): """ return self.output_table.to_csv(None) - def to_json(self): + def to_json(self, period='bill'): """ Output in json file + Args: + + period (str): 'month' for monthly + 'bill' for each bill period + default 'bill' + + 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): """