ziyuzhou02 commited on
Commit
77c60e3
·
verified ·
1 Parent(s): b0dcb71

GIFT-Eval style absolute metrics, Overall/By Domain tabs

Browse files
Files changed (1) hide show
  1. src/utils.py +65 -79
src/utils.py CHANGED
@@ -1,4 +1,3 @@
1
- import json
2
  import os
3
  import re
4
  from pathlib import Path
@@ -56,6 +55,8 @@ LEGACY_MODEL_NAMES = {
56
 
57
  def format_number(value):
58
  if isinstance(value, (int, float)):
 
 
59
  if abs(value) >= 10**2:
60
  return f"{value:.1e}"
61
  return f"{value:.3f}"
@@ -78,40 +79,6 @@ def unify_freq(df: pd.DataFrame) -> pd.DataFrame:
78
  return df
79
 
80
 
81
- def load_baseline_name(root_dir: str = "results") -> str:
82
- status_path = Path(root_dir) / "online_status.json"
83
- if status_path.exists():
84
- baseline = json.loads(status_path.read_text()).get("baseline_model")
85
- if baseline:
86
- return baseline
87
- return "Chronos-Bolt-Base"
88
-
89
-
90
- def standardize_df(df: pd.DataFrame, root_dir: str = "results") -> pd.DataFrame:
91
- df = df.copy()
92
- df["model"] = df["model"].replace(LEGACY_MODEL_NAMES)
93
-
94
- for metric in METRIC_COLUMNS:
95
- df[metric] = pd.to_numeric(df[metric], errors="coerce")
96
- df[metric] = df[metric].fillna(df[metric].mean())
97
-
98
- baseline_name = load_baseline_name(root_dir)
99
- if baseline_name not in set(df["model"]):
100
- return df
101
-
102
- group_keys = ["dataset", "term_length", "frequency"]
103
- for _, group in df.groupby(group_keys):
104
- baseline = group[group["model"] == baseline_name]
105
- if baseline.empty:
106
- continue
107
- idx = baseline.index[0]
108
- for metric in METRIC_COLUMNS:
109
- denom = baseline.at[idx, metric]
110
- if denom and denom != 0:
111
- df.loc[group.index, metric] = df.loc[group.index, metric] / denom
112
- return df
113
-
114
-
115
  def load_all_results(root_dir: str = "results") -> pd.DataFrame:
116
  frames = []
117
  for subdir, _, files in os.walk(root_dir):
@@ -143,6 +110,23 @@ def enrich_with_properties(df: pd.DataFrame, ds_properties_path: str) -> pd.Data
143
  return unify_freq(df)
144
 
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  def _add_per_dataset_ranks(df: pd.DataFrame) -> pd.DataFrame:
147
  df = df.copy()
148
  group_keys = ["dataset", "term_length", "frequency"]
@@ -155,14 +139,8 @@ def _add_per_dataset_ranks(df: pd.DataFrame) -> pd.DataFrame:
155
  def get_grouped_dfs(
156
  root_dir: str = "results",
157
  ds_properties: str | None = None,
158
- ) -> dict[str, pd.DataFrame]:
159
- if ds_properties is None:
160
- ds_properties = str(Path(root_dir) / "dataset_properties.csv")
161
-
162
- df = load_all_results(root_dir)
163
- df = enrich_with_properties(df, ds_properties)
164
- df = standardize_df(df, root_dir)
165
- df = _add_per_dataset_ranks(df)
166
 
167
  rank_cols = [f"Rank_{metric}" for metric in DISPLAY_METRICS]
168
  overall_values = df.groupby(["model"])[DISPLAY_METRICS].agg(stats.gmean)
@@ -173,26 +151,26 @@ def get_grouped_dfs(
173
  columns={f"Rank_{metric}": f"{METRIC_LABELS[metric]}_Rank" for metric in DISPLAY_METRICS}
174
  )
175
 
176
- domain_values: dict[str, pd.DataFrame] = {}
177
- domain_ranks: dict[str, pd.DataFrame] = {}
178
- domains = sorted(df["domain"].dropna().unique()) if "domain" in df.columns else []
179
- for domain in domains:
180
- subset = df[df["domain"] == domain]
181
  if subset.empty:
182
  continue
183
- values = subset.groupby(["model"])[DISPLAY_METRICS].agg(stats.gmean)
184
- ranks = subset.groupby(["model"])[rank_cols].mean()
185
- domain_values[domain] = values.rename(columns=METRIC_LABELS)
186
- domain_ranks[domain] = ranks.rename(
187
  columns={f"Rank_{metric}": f"{METRIC_LABELS[metric]}_Rank" for metric in DISPLAY_METRICS}
188
  )
 
 
189
 
190
  return {
191
  "overall_values": overall_values,
192
  "overall_ranks": overall_ranks,
193
- "domain_values": domain_values,
194
- "domain_ranks": domain_ranks,
195
- "domains": domains,
196
  }
197
 
198
 
@@ -210,27 +188,35 @@ def prepare_ranks_table(ranks_df: pd.DataFrame) -> pd.DataFrame:
210
  return table[cols].sort_values(by=["MASE_Rank"])
211
 
212
 
213
- def prepare_domain_summary(values_by_domain: dict[str, pd.DataFrame]) -> pd.DataFrame:
214
- rows = []
215
- for domain, values_df in sorted(values_by_domain.items()):
216
- for model, metrics in values_df.iterrows():
217
- row = {"Domain": domain, "Model": model}
218
- row.update(metrics.to_dict())
219
- rows.append(row)
220
- if not rows:
221
- return pd.DataFrame(columns=["Domain", "Model"] + VALUE_COLUMNS)
222
- table = pd.DataFrame(rows)
223
- return format_df(table.sort_values(by=["Domain", "MASE"]))
224
-
225
-
226
- def prepare_domain_rank_summary(ranks_by_domain: dict[str, pd.DataFrame]) -> pd.DataFrame:
227
- rows = []
228
- for domain, ranks_df in sorted(ranks_by_domain.items()):
229
- for model, metrics in ranks_df.iterrows():
230
- row = {"Domain": domain, "Model": model}
231
- row.update(metrics.to_dict())
232
- rows.append(row)
233
- if not rows:
234
- return pd.DataFrame(columns=["Domain", "Model"] + RANK_COLUMNS)
235
- table = pd.DataFrame(rows)
236
- return format_df(table.sort_values(by=["Domain", "MASE_Rank"]))
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import re
3
  from pathlib import Path
 
55
 
56
  def format_number(value):
57
  if isinstance(value, (int, float)):
58
+ if pd.isna(value):
59
+ return value
60
  if abs(value) >= 10**2:
61
  return f"{value:.1e}"
62
  return f"{value:.3f}"
 
79
  return df
80
 
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  def load_all_results(root_dir: str = "results") -> pd.DataFrame:
83
  frames = []
84
  for subdir, _, files in os.walk(root_dir):
 
110
  return unify_freq(df)
111
 
112
 
113
+ def prepare_results_df(
114
+ root_dir: str = "results",
115
+ ds_properties: str | None = None,
116
+ ) -> pd.DataFrame:
117
+ if ds_properties is None:
118
+ ds_properties = str(Path(root_dir) / "dataset_properties.csv")
119
+
120
+ df = load_all_results(root_dir)
121
+ if Path(ds_properties).exists():
122
+ df = enrich_with_properties(df, ds_properties)
123
+
124
+ for metric in METRIC_COLUMNS:
125
+ df[metric] = pd.to_numeric(df[metric], errors="coerce")
126
+
127
+ return _add_per_dataset_ranks(df)
128
+
129
+
130
  def _add_per_dataset_ranks(df: pd.DataFrame) -> pd.DataFrame:
131
  df = df.copy()
132
  group_keys = ["dataset", "term_length", "frequency"]
 
139
  def get_grouped_dfs(
140
  root_dir: str = "results",
141
  ds_properties: str | None = None,
142
+ ) -> dict[str, pd.DataFrame | list[str]]:
143
+ df = prepare_results_df(root_dir, ds_properties)
 
 
 
 
 
 
144
 
145
  rank_cols = [f"Rank_{metric}" for metric in DISPLAY_METRICS]
146
  overall_values = df.groupby(["model"])[DISPLAY_METRICS].agg(stats.gmean)
 
151
  columns={f"Rank_{metric}": f"{METRIC_LABELS[metric]}_Rank" for metric in DISPLAY_METRICS}
152
  )
153
 
154
+ datasets = sorted(df["dataset"].dropna().unique())
155
+ dataset_values: dict[str, pd.DataFrame] = {}
156
+ dataset_ranks: dict[str, pd.DataFrame] = {}
157
+ for dataset in datasets:
158
+ subset = df[df["dataset"] == dataset]
159
  if subset.empty:
160
  continue
161
+ values = subset.set_index("model")[DISPLAY_METRICS].rename(columns=METRIC_LABELS)
162
+ ranks = subset.set_index("model")[rank_cols].rename(
 
 
163
  columns={f"Rank_{metric}": f"{METRIC_LABELS[metric]}_Rank" for metric in DISPLAY_METRICS}
164
  )
165
+ dataset_values[dataset] = values
166
+ dataset_ranks[dataset] = ranks
167
 
168
  return {
169
  "overall_values": overall_values,
170
  "overall_ranks": overall_ranks,
171
+ "dataset_values": dataset_values,
172
+ "dataset_ranks": dataset_ranks,
173
+ "datasets": datasets,
174
  }
175
 
176
 
 
188
  return table[cols].sort_values(by=["MASE_Rank"])
189
 
190
 
191
+ def prepare_dataset_pivot(
192
+ df: pd.DataFrame,
193
+ metric: str,
194
+ *,
195
+ rank: bool = False,
196
+ ) -> pd.DataFrame:
197
+ """Pivot models × datasets (GIFT-Eval style by-domain view)."""
198
+ if rank:
199
+ value_col = f"Rank_{metric}"
200
+ label = f"{METRIC_LABELS[metric]}_Rank"
201
+ else:
202
+ value_col = metric
203
+ label = METRIC_LABELS[metric]
204
+
205
+ pivot = df.pivot_table(
206
+ index="model",
207
+ columns="dataset",
208
+ values=value_col,
209
+ aggfunc="first",
210
+ )
211
+ pivot = pivot.reset_index().rename(columns={"model": "Model"})
212
+ pivot.columns = [
213
+ "Model" if col == "Model" else str(col)
214
+ for col in pivot.columns
215
+ ]
216
+ pivot.columns.name = None
217
+ sort_col = "Model" if rank else pivot.columns[1] if len(pivot.columns) > 1 else "Model"
218
+ if sort_col != "Model" and sort_col in pivot.columns:
219
+ return format_df(pivot.sort_values(by=sort_col))
220
+ if rank and "MASE_Rank" in pivot.columns:
221
+ return format_df(pivot.sort_values(by="MASE_Rank"))
222
+ return format_df(pivot.sort_values(by="Model"))