Source code for tailestim.estimators.result

from typing import Any, ClassVar, Dict, Optional

import numpy as np


[docs] class TailEstimatorResult: """ Class for storing the results of a tail estimator. Attributes available depends on the estimator used. Attributes ---------- estimator : BaseTailEstimator The estimator instance (e.g., HillEstimator, PickandsEstimator, etc.) used for estimation. xi_star_ : float Optimal tail index estimate (ξ). gamma_ : float Power law exponent (γ). k_arr_ : np.ndarray Array of order statistics. xi_arr_ : np.ndarray Array of tail index estimates. k_star_ : float Optimal order statistic (k*). bootstrap_results_ : dict Bootstrap results. k_min_ : float Minimum AMSE fraction. amse_ : np.ndarray AMSE values. max_index_ : int Maximum index. x_arr_ : np.ndarray Fraction of order statistics. """ # Mapping of keys to human-readable labels _key_labels: ClassVar[Dict[str, str]] = { "estimator": "Estimator", "xi_star_": "Tail index (ξ)", "gamma_": "Power law exponent (γ)", "k_arr_": "Order statistics", "xi_arr_": "Tail index estimates", "k_star_": "Optimal order statistic (k*)", "bootstrap_results_": "Bootstrap Results", "first_bootstrap_": "First Bootstrap", "second_bootstrap_": "Second Bootstrap", "k_min_": "Minimum AMSE fraction", "amse_": "AMSE values", "max_index_": "Maximum index", "x_arr_": "Fraction of order statistics", } def __init__(self, initial_data: Optional[Dict[str, Any]] = None, **kwargs): data = initial_data or {} data.update(kwargs) # Recursively convert nested dicts to TailEstimatorResult objects. for key, value in data.items(): if isinstance(value, dict): data[key] = TailEstimatorResult(value) self.__dict__.update(data)
[docs] def __str__(self, include_header=True) -> str: """ Return a human-readable string representation of the TailEstimatorResult. Parameters ---------- include_header : bool, default=True Whether to include the "Result" header. This is set to False for nested objects. """ output = [] from .base import BaseTailEstimator # Add a header for the result section, but only for the top-level object if include_header: output.extend(["-" * 50, "Result", "-" * 50]) # Order the attributes based on the keys in _key_labels ordered_keys = [k for k in self._key_labels if k in self.__dict__] # Add any keys that aren't in _key_labels at the end ordered_keys.extend([k for k in self.__dict__ if k not in self._key_labels]) for key in ordered_keys: value = self.__dict__[key] label = self._key_labels.get(key, key.replace("_", " ").title()) # Format the value based on its type if isinstance(value, BaseTailEstimator): # Print estimator type value_str = f"{value.__class__.__name__}" elif isinstance(value, np.ndarray): if len(value) > 5: # For large arrays, show shape and a few values value_str = f"Array of shape {value.shape} [{', '.join(f'{v:.4f}' for v in value[:3])}, ...]" else: # For small arrays, show all values value_str = f"[{', '.join(f'{v:.4f}' for v in value)}]" elif isinstance(value, float): value_str = f"{value:.4f}" elif isinstance(value, TailEstimatorResult): # For nested TailEstimatorResult objects, indent their string representation # but don't include the header nested_str = value.__str__(include_header=False).replace("\n", "\n ") value_str = f"\n {nested_str}" else: value_str = str(value) output.append(f"{label}: {value_str}") return "\n".join(output)
[docs] def __repr__(self) -> str: """ Return a string representation of the TailEstimatorResult. """ return f"TailEstimatorResult(estimator={self.estimator.__class__.__name__})"