def _set_model_instance(self): try: self.model_instance = hts_models.MODEL_MAPPING[self.model] except KeyError: raise InvalidArgumentException( f'Model {self.model} not valid. Pick one of: {" ".join(ModelT.names())}' )
def __init_hts( self, nodes: Optional[NodesT] = None, df: Optional[pandas.DataFrame] = None, tree: Optional[HierarchyTree] = None, root: str = "root", exogenous: Optional[List[str]] = None, ): if not nodes and not df: if not tree: raise InvalidArgumentException( "Either nodes and df must be passed, or a pre-built hierarchy tree" ) else: self.nodes = tree else: self.nodes = HierarchyTree.from_nodes(nodes=nodes, df=df, exogenous=exogenous, root=root) self.exogenous = exogenous self.sum_mat, sum_mat_labels = to_sum_mat(self.nodes) self._set_model_instance() self._init_revision()
def groupify(root_node, df, freq='1H', nodes=None, min_count=0.1, total=None) -> NAryTreeT: """ Parameters ---------- fillna root_node : NAryTreeT df : pandas.DataFrame freq : str resample frequency nodes : tuple Hierarchy node min_count : int or float Minimum number of observations for a node to be used. If float, it represents a fraction of values that need to be non NaNs and must be between 0 and 1 total : pandas.DataFrame: Name of root node Returns ------- """ child_group = nodes[0] # city children = df[child_group].unique() # berlin, munich, ... # add first level children for child in children: sub_df = df[df[child_group] == child] resampled = resample_count(sub_df, freq, child) root_node.add_child(key=child, item=resampled, exogenous=None) # add the rest for node in nodes[1:]: parent_group = child_group child_group = node # hex_index_6 children = df[child_group].unique() # abcccc, abccf, ... for child in children: sub_df = df[df[child_group] == child] if isinstance(min_count, float): allowance = len(total) * min_count elif isinstance(min_count, int): allowance = min_count else: raise InvalidArgumentException( f'min_count must be either float or integer') if len(sub_df) < allowance: continue parent_name = sub_df[parent_group].value_counts().index[0] resampled = resample_count(sub_df, freq, child) for c in root_node.traversal_level(): if c.key == parent_name: c.add_child(key=child, item=resampled, exogenous=None) return root_node
def __init__( self, kind: str, node: HierarchyTree, transform: TransformT = False, **kwargs ): """ Parameters ---------- kind : str One of `prophet`, `sarimax`, `auto-arima`, `holt-winters` node : HierarchyTree Node transform : Bool or NamedTuple kwargs Keyword arguments to be passed to the model instantiation. See the documentation of each of the actual model implementations for a more comprehensive treatment """ if kind not in ModelT.names(): raise InvalidArgumentException( f'Model {kind} not valid. Pick one of: {" ".join(ModelT.names())}' ) self.kind = kind self.node = node self.transform_function = self._set_transform(transform=transform) self.model = self.create_model(**kwargs) self.forecast = None self.residual = None self.mse = None
def revise(self, forecasts=None, mse=None, nodes=None): """ Parameters ---------- forecasts mse nodes Returns ------- """ if self.name == MethodsT.NONE.name: return y_hat_matrix(forecasts=forecasts) if self.name in [ MethodsT.OLS.name, MethodsT.WLSS.name, MethodsT.WLSV.name ]: return optimal_combination(forecasts=forecasts, sum_mat=self.sum_mat, method=MethodsT.OLS.name, mse=mse) elif self.name == MethodsT.BU.name: print("Name:::" + str(self.name)) print(list(forecasts.keys())) y_hat = self._y_hat_matrix(forecasts) return self._new_mat(y_hat) elif self.name in [MethodsT.AHP.name, MethodsT.PHA.name]: if self.transformer: for node in make_iterable(nodes, prop=None): node.item[node.key] = self.transformer.inverse_transform( node.item[node.key]) y_hat = proportions(nodes=nodes, forecasts=forecasts, sum_mat=self.sum_mat, method=self.name) return self._new_mat(y_hat) elif self.name == MethodsT.FP.name: return forecast_proportions(forecasts, nodes) else: raise InvalidArgumentException('Revision model name is invalid')