Liang commited on
Commit
fdfbcd0
·
unverified ·
2 Parent(s): de0e636d381333

Merge pull request #6 from cyc00518/feature/score-threshold-filter

Browse files
Files changed (2) hide show
  1. README.md +8 -0
  2. app.py +73 -1
README.md CHANGED
@@ -23,6 +23,14 @@
23
  - `accuracy_mean`
24
  - `source_label`(模型名稱 + timestamp)
25
  - 提供整體平均值的計算,缺漏時自動補足。
 
 
 
 
 
 
 
 
26
  - 視覺化:
27
  - 各類別的柱狀圖(依模型分組對照)。
28
  - 可選擇排序方式(平均由高→低、平均由低→高、字母排序)。
 
23
  - `accuracy_mean`
24
  - `source_label`(模型名稱 + timestamp)
25
  - 提供整體平均值的計算,缺漏時自動補足。
26
+ - **分數閾值篩選**:
27
+ - 支援兩種篩選模式:
28
+ - **任一模型符合**:只要有任一個模型在該類別符合條件,就顯示該類別和所有模型的分數。
29
+ - **特定模型符合**:篩選特定模型符合條件的類別(需選擇要篩選的模型)。
30
+ - 可設定閾值條件:≥ 或 ≤ 特定分數。
31
+ - 根據顯示比例(0–1 或 0–100)自動調整閾值範圍。
32
+ - 篩選後自動更新圖表、分頁顯示及排序。
33
+ - 若無符合條件的類別,顯示提示訊息。
34
  - 視覺化:
35
  - 各類別的柱狀圖(依模型分組對照)。
36
  - 可選擇排序方式(平均由高→低、平均由低→高、字母排序)。
app.py CHANGED
@@ -108,6 +108,38 @@ with st.sidebar:
108
  page_size = st.selectbox("每張圖顯示幾個類別", [10, 20, 30, 50, 100], index=1)
109
  sort_mode = st.selectbox("排序方式(原始成績)", ["依整體平均由高到低", "依整體平均由低到高", "依字母排序"])
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  # === Baseline Δ 圖表的控制 ===
112
  st.markdown("---")
113
  st.subheader("差距分析設定(Baseline Δ)")
@@ -129,7 +161,32 @@ work = df_all[df_all["dataset"] == selected_dataset].copy()
129
  metric_plot = "accuracy_mean" + (" (x100)" if normalize_0_100 else "")
130
  work[metric_plot] = work["accuracy_mean"] * (100.0 if normalize_0_100 else 1.0)
131
 
132
- order_df = work.groupby("category")[metric_plot].mean().reset_index()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  if sort_mode == "依整體平均由高到低":
134
  order_df = order_df.sort_values(metric_plot, ascending=False)
135
  elif sort_mode == "依整體平均由低到高":
@@ -138,12 +195,27 @@ else:
138
  order_df = order_df.sort_values("category", ascending=True)
139
 
140
  cat_order = order_df["category"].tolist()
 
 
 
 
 
 
 
 
 
 
 
141
  work["category"] = pd.Categorical(work["category"], categories=cat_order, ordered=True)
142
 
143
  n = len(cat_order)
144
  pages = int(np.ceil(n / page_size))
145
 
146
  st.markdown("## 📈 原始成績(各模型 × 類別)")
 
 
 
 
147
  for p in range(pages):
148
  start, end = p * page_size, min((p + 1) * page_size, n)
149
  subset_cats = cat_order[start:end]
 
108
  page_size = st.selectbox("每張圖顯示幾個類別", [10, 20, 30, 50, 100], index=1)
109
  sort_mode = st.selectbox("排序方式(原始成績)", ["依整體平均由高到低", "依整體平均由低到高", "依字母排序"])
110
 
111
+ # === 分數閾值篩選 ===
112
+ st.markdown("---")
113
+ st.subheader("📏 分數篩選(原始成績)")
114
+ enable_threshold = st.checkbox("啟用分數閾值篩選", value=False)
115
+ if enable_threshold:
116
+ threshold_mode = st.radio("篩選模式", ["顯示 ≥ 閾值", "顯示 ≤ 閾值"])
117
+
118
+ # 篩選依據選擇
119
+ filter_basis = st.radio(
120
+ "篩選依據",
121
+ ["任一模型符合", "特定模型符合"],
122
+ help="任一模型符合:只要有任一個模型在該類別符合條件就顯示\n特定模型符合:只篩選特定模型的分數"
123
+ )
124
+
125
+ specific_model = None
126
+ if filter_basis == "特定模型符合":
127
+ all_models = sorted(df_all["source_label"].unique().tolist()) if not df_all.empty else []
128
+ if all_models:
129
+ specific_model = st.selectbox("選擇模型", options=all_models)
130
+
131
+ # 根據顯示模式決定預設值與範圍
132
+ if normalize_0_100:
133
+ threshold_value = st.slider("閾值", min_value=0.0, max_value=100.0, value=50.0, step=1.0)
134
+ else:
135
+ threshold_value = st.slider("閾值", min_value=0.0, max_value=1.0, value=0.5, step=0.01)
136
+ st.caption(f"{'≥' if threshold_mode == '顯示 ≥ 閾值' else '≤'} {threshold_value}")
137
+ else:
138
+ threshold_mode = None
139
+ threshold_value = None
140
+ filter_basis = None
141
+ specific_model = None
142
+
143
  # === Baseline Δ 圖表的控制 ===
144
  st.markdown("---")
145
  st.subheader("差距分析設定(Baseline Δ)")
 
161
  metric_plot = "accuracy_mean" + (" (x100)" if normalize_0_100 else "")
162
  work[metric_plot] = work["accuracy_mean"] * (100.0 if normalize_0_100 else 1.0)
163
 
164
+ # === 套用閾值篩選 ===
165
+ if enable_threshold and threshold_value is not None:
166
+ if filter_basis == "任一模型符合":
167
+ # 篩選方式:只要有任一模型在該類別符合條件
168
+ if threshold_mode == "顯示 ≥ 閾值":
169
+ # 保留那些「至少有一個模型 ≥ 閾值」的類別
170
+ valid_cats = work[work[metric_plot] >= threshold_value]["category"].unique().tolist()
171
+ else: # "顯示 ≤ 閾值"
172
+ # 保留那些「至少有一個模型 ≤ 閾值」的類別
173
+ valid_cats = work[work[metric_plot] <= threshold_value]["category"].unique().tolist()
174
+ work = work[work["category"].isin(valid_cats)]
175
+ # 計算平均用於排序
176
+ order_df = work.groupby("category")[metric_plot].mean().reset_index()
177
+ else: # "特定模型符合"
178
+ # 只篩選特定模型的資料,然後依該模型判斷
179
+ work_specific = work[work["source_label"] == specific_model]
180
+ if threshold_mode == "顯示 ≥ 閾值":
181
+ valid_cats = work_specific[work_specific[metric_plot] >= threshold_value]["category"].unique().tolist()
182
+ else: # "顯示 ≤ 閾值"
183
+ valid_cats = work_specific[work_specific[metric_plot] <= threshold_value]["category"].unique().tolist()
184
+ # 保留符合條件的類別,但顯示所有模型
185
+ work = work[work["category"].isin(valid_cats)]
186
+ order_df = work.groupby("category")[metric_plot].mean().reset_index()
187
+ else:
188
+ order_df = work.groupby("category")[metric_plot].mean().reset_index()
189
+
190
  if sort_mode == "依整體平均由高到低":
191
  order_df = order_df.sort_values(metric_plot, ascending=False)
192
  elif sort_mode == "依整體平均由低到高":
 
195
  order_df = order_df.sort_values("category", ascending=True)
196
 
197
  cat_order = order_df["category"].tolist()
198
+
199
+ # 如果篩選後沒有類別,顯示提示
200
+ if not cat_order:
201
+ if enable_threshold and threshold_mode is not None and threshold_value is not None:
202
+ st.warning(
203
+ f"⚠️ 沒有類別符合篩選條件({threshold_mode}: {threshold_value}),請調整閾值或關閉篩選。"
204
+ )
205
+ else:
206
+ st.warning("⚠️ 沒有可顯示的類別,請檢查資料集內容或調整篩選條件。")
207
+ st.stop()
208
+
209
  work["category"] = pd.Categorical(work["category"], categories=cat_order, ordered=True)
210
 
211
  n = len(cat_order)
212
  pages = int(np.ceil(n / page_size))
213
 
214
  st.markdown("## 📈 原始成績(各模型 × 類別)")
215
+ if enable_threshold and threshold_mode is not None:
216
+ filter_info = f"任一模型符合" if filter_basis == "任一模型符合" else f"模型 {specific_model} 符合"
217
+ st.info(f"🔍 已啟用篩選({filter_info}):顯示平均分數 {threshold_mode.replace('顯示 ', '')} {threshold_value} 的類別(共 {n} 個)")
218
+
219
  for p in range(pages):
220
  start, end = p * page_size, min((p + 1) * page_size, n)
221
  subset_cats = cat_order[start:end]