Example of usage of data for further modelling¶
In this demo we will show you how to load and use data in preheat.
[1]:
# Load packages from preheat and time management
from preheat_open import set_logging_level, test
set_logging_level("WARNING") # prevent annoying info logs from printing
from preheat_open.building import Building
from datetime import datetime, timedelta
import pandas as pd
pd.options.plotting.backend = "plotly"
2022-03-18 11:59:28,031 INFO api Loading config from /home/ask/.preheat/config.json .(api.py:126)
Let us consider a test-location
[2]:
building = Building(2371)
To access energy data we query for a list of heating
units (there’s only one)
[3]:
heating = building.qu("heating")
print("Heating unit: ", heating)
Heating unit: heating(heating_7252)
Let us consider the components of the heating unit
[4]:
print("The indoor climate unit has the following components: ", heating.components)
The indoor climate unit has the following components: [Component(primaryReturnT, HEAT_RETURN_TEMP (S5))]
Unfortunately, the heating unit only has the return temperature mapped not any energy meter. We must infer the energy from the difference between main and hot water. (We could also traverse down the tree of the heating unit and check if the secondaries that belong to it have energy meters, however, we refrain from that in this tutorial.)
[5]:
main = building.qu("main")
print("Main:", main)
hot_water = building.qu("hotWater")
print("Hot water:", hot_water)
Main: [main(Hus 11 Main), main(MAIN [10+11])]
Hot water: hotWater(Hus 11 Varmt brugsvand)
It appears that this location shares its main unit with another location (the MAIN [10+11]
) however, the unit Hus 11 Main
provides us with information for only this location.
[6]:
main = main[0]
Let us check that these have the desired meters
[7]:
for u in [main, hot_water]:
print(f"Components of {u.unit_type}:", u.components)
Components of main: [Component(supplyT, FLOW_TEMPERATURE), Component(returnT, RETURN_TEMPERATURE), Component(flow, VOLUME_FLOW), Component(volume, VOLUME), Component(energy, ENERGY), Component(power, POWER)]
Components of hotWater: [Component(primarySupplyT, FLOW_TEMPERATURE), Component(primaryReturnT, RETURN_TEMPERATURE), Component(primaryFlow, VOLUME_FLOW), Component(volume, VOLUME), Component(energy, ENERGY), Component(power, POWER)]
Luckily, they both provide power readings. Let us load the daily average power consumption for the past three months and approximate the consumption as the difference between the two. To avoid wasting effort on loading all available data, we restrict to the component “power” (you can leave components
unspecified to load all data!)
[8]:
end = datetime.now()
start = end - timedelta(days=90)
resolution = "hour"
df = pd.DataFrame()
for u in [main, hot_water]:
u.load_data(start,end,resolution, components=["power"])
df[u.unit_type] = u.data["power"]
df["heating"] = df[main.unit_type] - df[hot_water.unit_type]
df.describe().transpose()
[8]:
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
main | 2157.0 | 46.093011 | 13.453564 | 7.266667 | 39.225000 | 48.218182 | 54.916667 | 83.036364 |
hotWater | 2158.0 | 5.766640 | 3.574115 | 1.600000 | 2.955492 | 4.713636 | 7.448864 | 25.760000 |
heating | 2157.0 | 40.324532 | 12.962233 | 3.541667 | 34.383333 | 43.036364 | 48.063636 | 79.927273 |
While we are at it, let us load the weather information for the same period and append the data to our dataframe. Note that as a rule of thumb, the weather components begin with a capital letter. That allows us to distinguish the indoor temperature
(a component of the indoor climate units) from the outdoor Temperature
etc. We load the ambient temperature and the incoming sun power.
[9]:
weather = building.weather
print("Weather components:", weather.components)
weather_components = ["Temperature", "DirectSunPowerVertical", "DiffuseSunPower"]
weather.load_data(start,end,resolution, components=weather_components)
df[weather_components] = weather.data[weather_components]
df.describe().transpose()
Weather components: [Component(Temperature, None), Component(Humidity, None), Component(WindDirection, None), Component(WindSpeed, None), Component(Pressure, None), Component(LowClouds, None), Component(MediumClouds, None), Component(HighClouds, None), Component(Fog, None), Component(WindGust, None), Component(DewPointTemperature, None), Component(Cloudiness, None), Component(Precipitation, None), Component(DirectSunPower, None), Component(DiffuseSunPower, None), Component(SunAltitude, None), Component(SunAzimuth, None), Component(DirectSunPowerVertical, None)]
[9]:
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
main | 2157.0 | 46.093011 | 13.453564 | 7.266667 | 39.225000 | 48.218182 | 54.916667 | 83.036364 |
hotWater | 2158.0 | 5.766640 | 3.574115 | 1.600000 | 2.955492 | 4.713636 | 7.448864 | 25.760000 |
heating | 2157.0 | 40.324532 | 12.962233 | 3.541667 | 34.383333 | 43.036364 | 48.063636 | 79.927273 |
Temperature | 2159.0 | 3.425938 | 2.605860 | -5.500000 | 1.700000 | 3.300000 | 5.500000 | 9.600000 |
DirectSunPowerVertical | 2159.0 | 0.118278 | 0.207390 | 0.000000 | 0.000000 | 0.000000 | 0.156606 | 0.741441 |
DiffuseSunPower | 2159.0 | 0.014667 | 0.027488 | 0.000000 | 0.000000 | 0.000000 | 0.016838 | 0.153348 |
We can use the acquired data to construct a simple linear model for the heating energy demand
[10]:
import statsmodels.formula.api as smf
res = smf.ols("heating ~ 1 + Temperature + DirectSunPowerVertical + DiffuseSunPower", df).fit()
res.summary()
[10]:
Dep. Variable: | heating | R-squared: | 0.479 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.479 |
Method: | Least Squares | F-statistic: | 660.5 |
Date: | Fri, 18 Mar 2022 | Prob (F-statistic): | 2.25e-304 |
Time: | 11:59:29 | Log-Likelihood: | -7882.7 |
No. Observations: | 2157 | AIC: | 1.577e+04 |
Df Residuals: | 2153 | BIC: | 1.580e+04 |
Df Model: | 3 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | 49.4827 | 0.341 | 145.220 | 0.000 | 48.814 | 50.151 |
Temperature | -1.3682 | 0.079 | -17.352 | 0.000 | -1.523 | -1.214 |
DirectSunPowerVertical | -27.9668 | 1.548 | -18.061 | 0.000 | -31.003 | -24.930 |
DiffuseSunPower | -79.4236 | 11.723 | -6.775 | 0.000 | -102.413 | -56.434 |
Omnibus: | 9.255 | Durbin-Watson: | 0.777 |
---|---|---|---|
Prob(Omnibus): | 0.010 | Jarque-Bera (JB): | 10.786 |
Skew: | -0.082 | Prob(JB): | 0.00455 |
Kurtosis: | 3.305 | Cond. No. | 256. |
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
Let us investigate the quality of the fit
[ ]: