Energy Signature

Energy Signature#

Goal

Plot an energy signature: daily heating energy against the daily mean outdoor temperature, colored by season. The cloud shows how the heating demand rises as it gets colder; where it drops to zero lies roughly the balance point temperature (fitted with regression lines in Energy Signature (PES)).

Data Basis

Building energy signature data (bldg_engy_sig_simple.csv) bundled with the pyedautils package. Contains columns timestamp, temperature, and value (daily heating energy).

Data Preparation#

import numpy as np
import pandas as pd
from importlib import resources

data_path = resources.files("pyedautils") / "data" / "bldg_engy_sig_simple.csv"
df = pd.read_csv(data_path, sep=";")

def remove_outliers_by_temp_bin(df, temp_col, value_col, bin_width=2,
                                lower_q=0.01, upper_q=0.99):
    """Remove rows where value_col falls outside the per-temperature-bin quantiles."""
    df = df.copy()
    df["_bin"] = pd.cut(df[temp_col], bins=np.arange(
        df[temp_col].min() - bin_width,
        df[temp_col].max() + bin_width * 2,
        bin_width,
    ))
    bounds = df.groupby("_bin", observed=True)[value_col].quantile(
        [lower_q, upper_q]
    ).unstack()
    bounds.columns = ["lo", "hi"]
    df = df.join(bounds, on="_bin")
    mask = df[value_col].between(df["lo"], df["hi"])
    print(f"Removed {(~mask).sum()} outliers out of {len(df)} rows")
    return df.loc[mask].drop(columns=["_bin", "lo", "hi"])

df = remove_outliers_by_temp_bin(df, "temperature", "value")
df.head()
Removed 29 outliers out of 576 rows
timestamp temperature value
0 2018-03-21 2.82 176.54
1 2018-03-22 1.08 196.75
2 2018-03-23 5.33 148.92
3 2018-03-24 9.90 101.15
4 2018-03-25 9.11 100.82

Visualization#

from pyedautils.plots import plot_energy_signature

fig = plot_energy_signature(
    data=df,
    title="Building Energy Signature",
    xlab="Outside Temperature [°C]",
    ylab="Heating Energy [kWh/d]",
)
fig.show()
Customization

You can adjust the axis labels and title. To analyze a different time period, filter the DataFrame before plotting.

df["timestamp"] = pd.to_datetime(df["timestamp"])
df_winter = df[df["timestamp"].dt.month.isin([11, 12, 1, 2, 3])]
fig = plot_energy_signature(df_winter, title="Energy Signature — Winter Only")