Source code for accim.parametric_and_optimisation.utils

# accim - Adaptive-Comfort-Control-Implemented Model
# Copyright (C) 2021-2025 Daniel Sánchez-García

# accim is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.

# accim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import numpy as np


[docs] def descriptor_has_options(values): #Checking value entered is a list containing floats or a tuple containing the minimum and maximum values descriptor_has_options = False if type(values) == tuple and len(values) == 2 and all([type(i) == float or type(i) == int or type(i) == np.float64 for i in values]): pass elif type(values) == list and all(type(j) == float or type(j) == int or type(j) == np.float64 for j in values): descriptor_has_options = True else: raise ValueError('values argument must be, FOR ALL CASES, ' 'a list containing int or float, ' 'or a tuple which contains the minimum and maximum values for the range') return descriptor_has_options
import pandas as pd import ast from datetime import datetime, timedelta
[docs] def expand_to_hourly_dataframe( df: pd.DataFrame, parameter_columns: list, start_date: str = '2024-01-01 01', hourly_columns: list = None, ): """ Expands a dataframe with hourly data columns into an hourly dataframe. Parameters: df (pd.DataFrame): The input dataframe containing parameters and hourly data columns. parameter_columns (list): The list of column names that contain input parameters. start_date (str): The start date and time in the format 'YYYY-MM-DD HH'. Returns: pd.DataFrame: The expanded dataframe with an additional datetime column. """ # Identify columns with hourly data if hourly_columns is None: hourly_columns = identify_hourly_columns(df) # print(f"Hourly columns identified: {hourly_columns}") # Keep only parameter columns and hourly columns df_subset = df[parameter_columns + hourly_columns].copy() # Convert string representations of lists into actual lists for col in hourly_columns: # print(f"Processing column: {col}") if not df_subset[col].empty and isinstance(df_subset[col].iloc[0], str): print(f"First element of '{col}' is a string. Attempting evaluation...") evaluated_values = [] for value in df_subset[col]: try: evaluated_values.append(ast.literal_eval(value.strip())) except (ValueError, TypeError, SyntaxError, Exception) as e: print(f"Error evaluating in column '{col}': '{value}' - {e}") evaluated_values.append(None) df_subset[col] = evaluated_values else: continue # print(f"First element of '{col}' is not a string. Assuming it's already a list.") # Convert start_date to datetime object start_datetime = datetime.strptime(start_date, '%Y-%m-%d %H') # Function to expand the dataframe for hourly data def expand_hourly_data(row): num_hours = len(row[hourly_columns[0]]) expanded_rows = {col: [row[col]] * num_hours for col in parameter_columns} expanded_rows['hour'] = list(range(1, num_hours + 1)) expanded_rows['datetime'] = [start_datetime + timedelta(hours=i) for i in range(num_hours)] for col in hourly_columns: expanded_rows[col] = row[col] return pd.DataFrame(expanded_rows) # Apply the function to each row and concatenate the results expanded_df = pd.concat(df_subset.apply(expand_hourly_data, axis=1).to_list(), ignore_index=True) return expanded_df
[docs] def identify_hourly_columns(df): """ Identifies the columns which contains strings representing lists. :param df: the pandas DataFrame :return: the list of column names """ hourly_columns = [ col for col in df.columns if df[col].apply(lambda x: isinstance(x, str) and x.startswith('[') and x.endswith(']')).all() ] if not hourly_columns: hourly_columns = [ col for col in df.columns if df[col].astype(str).apply(lambda x: x.strip().startswith('[') and x.strip().endswith(']')).all() ] return hourly_columns
[docs] def make_all_combinations(parameters_values_dict: dict) -> pd.DataFrame: """ Takes all values from all the parameters and return a pandas DataFrame with all possible combinations. :param parameters_values_dict: a dictionary in the format {'parameter name': list_of_values} :return: a pandas DataFrame with all possible combinations """ from itertools import product combinations = list(product(*parameters_values_dict.values())) parameters_values_df = pd.DataFrame(combinations, columns=parameters_values_dict.keys()) return parameters_values_df