Lashtw commited on
Commit
3d61168
·
verified ·
1 Parent(s): fa3d984

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -28
app.py CHANGED
@@ -9,13 +9,10 @@ import os
9
  import matplotlib.font_manager as fm
10
 
11
  # ============================
12
- # 字型載入與設定 (修正重點)
13
  # ============================
14
 
15
- # 指定字型檔路徑
16
- font_path = "NotoSansTC-Regular.ttf" # 確認此檔案在工作目錄中
17
-
18
- # 載入本地字型檔,並取得字型名稱
19
  if os.path.exists(font_path):
20
  fm.fontManager.addfont(font_path)
21
  font_prop = fm.FontProperties(fname=font_path)
@@ -24,19 +21,20 @@ else:
24
  st.error(f"找不到字型檔: {font_path}")
25
  CHINESE_FONT = "Noto Sans TC" # fallback
26
 
27
- # 設定 Kaleido 全局參數
28
  pio.kaleido.scope.default_font = CHINESE_FONT
29
  pio.kaleido.scope.default_format = "png"
30
  pio.kaleido.scope.default_width = 1200
31
  pio.kaleido.scope.default_height = 900
32
  pio.kaleido.scope.default_scale = 2
33
-
34
- # ★ 關鍵:告訴 Kaleido 額外字型的對應關係
35
  pio.kaleido.scope.extra_fonts = {CHINESE_FONT: font_path}
36
 
 
 
 
37
 
38
  def setup_chinese_font():
39
- """系統體檢查與安裝"""
40
  try:
41
  test_fig, ax = plt.subplots()
42
  ax.text(0.5, 0.5, "中文測試", fontfamily=CHINESE_FONT)
@@ -47,17 +45,19 @@ def setup_chinese_font():
47
  os.system('apt-get update && apt-get install -y --force-yes fonts-noto-cjk')
48
  st.experimental_rerun()
49
 
 
 
 
 
50
  def load_data(uploaded_file):
51
- """数据加载函数"""
52
  try:
53
  df = pd.read_csv(uploaded_file, encoding='utf-8').dropna(how='all')
54
-
55
  if '姓名' not in df.columns:
56
- raise ValueError("CSV文件中缺少必要欄位:姓名")
57
-
58
  numeric_columns = []
59
  potential_numeric = ['平均', '總分', '國文', '英文', '數學', '自科',
60
- '社會', '地理', '歷史', '公民', '物理', '化學', '生物']
61
  for col in potential_numeric:
62
  if col in df.columns:
63
  try:
@@ -65,17 +65,19 @@ def load_data(uploaded_file):
65
  numeric_columns.append(col)
66
  except:
67
  pass
68
-
69
  if not numeric_columns:
70
- raise ValueError("CSV文件中未找到有效的數值欄位")
71
-
72
  return df, numeric_columns
73
  except Exception as e:
74
  st.error(f"數據加載錯誤:{str(e)}")
75
  return None, None
76
 
 
 
 
 
77
  def create_radar_chart(df, selected_rows, selected_columns, student_name=""):
78
- """生成雷達圖"""
79
  fig = go.Figure()
80
  line_styles = ['solid', 'dot', 'dash', 'longdash', 'dashdot']
81
  colors = ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728', '#9467BD']
@@ -131,8 +133,12 @@ def create_radar_chart(df, selected_rows, selected_columns, student_name=""):
131
  )
132
  return fig
133
 
 
 
 
 
134
  def generate_radar_image(fig):
135
- """生成圖片 (強制配置與更新字型設定)"""
136
  try:
137
  # 重設 kaleido 配置(含 extra_fonts)
138
  pio.kaleido.scope.default_font = CHINESE_FONT
@@ -181,6 +187,10 @@ def generate_radar_image(fig):
181
  st.error(f"圖片生成失敗: {str(e)}")
182
  return None
183
 
 
 
 
 
184
  def main():
185
  st.title('學生成績雷達圖產生器')
186
  st.markdown("""
@@ -195,7 +205,7 @@ def main():
195
  </style>
196
  """, unsafe_allow_html=True)
197
 
198
- setup_chinese_font() # 檢查字型
199
 
200
  uploaded_file = st.file_uploader("上傳CSV檔案", type=['csv'])
201
  if uploaded_file is not None:
@@ -232,6 +242,7 @@ def main():
232
  target_students = [s for s in all_students if s not in current_comparison]
233
  for idx, student in enumerate(target_students):
234
  try:
 
235
  fig = create_radar_chart(
236
  df,
237
  current_comparison + [student],
@@ -243,14 +254,14 @@ def main():
243
  image_bytes[student] = img
244
  except Exception as e:
245
  st.error(f"生成 {student} 圖表失敗:{str(e)}")
246
- progress_bar.progress((idx+1)/len(target_students))
247
  if image_bytes:
248
- st.write("### 圖表預覽")
249
- cols = st.columns(3)
250
- for i, (student, img) in enumerate(image_bytes.items()):
251
- with cols[i % 3]:
252
- st.image(img, use_container_width=True)
253
- st.caption(f"{student} 比較圖")
254
  zip_buffer = BytesIO()
255
  with ZipFile(zip_buffer, "w") as zip_file:
256
  for student, img in image_bytes.items():
@@ -265,4 +276,4 @@ def main():
265
  )
266
 
267
  if __name__ == "__main__":
268
- main()
 
9
  import matplotlib.font_manager as fm
10
 
11
  # ============================
12
+ # 載入本地字型檔與設定
13
  # ============================
14
 
15
+ font_path = "NotoSansTC-Regular.ttf" # 確認此字型檔路徑正確
 
 
 
16
  if os.path.exists(font_path):
17
  fm.fontManager.addfont(font_path)
18
  font_prop = fm.FontProperties(fname=font_path)
 
21
  st.error(f"找不到字型檔: {font_path}")
22
  CHINESE_FONT = "Noto Sans TC" # fallback
23
 
24
+ # 配置 Kaleido 的預設參數與額外字型設定
25
  pio.kaleido.scope.default_font = CHINESE_FONT
26
  pio.kaleido.scope.default_format = "png"
27
  pio.kaleido.scope.default_width = 1200
28
  pio.kaleido.scope.default_height = 900
29
  pio.kaleido.scope.default_scale = 2
 
 
30
  pio.kaleido.scope.extra_fonts = {CHINESE_FONT: font_path}
31
 
32
+ # ============================
33
+ # 系統字型檢查與安裝
34
+ # ============================
35
 
36
  def setup_chinese_font():
37
+ """檢查系統中文型是否可用,若無則嘗試安裝"""
38
  try:
39
  test_fig, ax = plt.subplots()
40
  ax.text(0.5, 0.5, "中文測試", fontfamily=CHINESE_FONT)
 
45
  os.system('apt-get update && apt-get install -y --force-yes fonts-noto-cjk')
46
  st.experimental_rerun()
47
 
48
+ # ============================
49
+ # 資料讀取
50
+ # ============================
51
+
52
  def load_data(uploaded_file):
53
+ """從 CSV 檔案中讀取資料"""
54
  try:
55
  df = pd.read_csv(uploaded_file, encoding='utf-8').dropna(how='all')
 
56
  if '姓名' not in df.columns:
57
+ raise ValueError("CSV檔案中缺少必要欄位:姓名")
 
58
  numeric_columns = []
59
  potential_numeric = ['平均', '總分', '國文', '英文', '數學', '自科',
60
+ '社會', '地理', '歷史', '公民', '物理', '化學', '生物']
61
  for col in potential_numeric:
62
  if col in df.columns:
63
  try:
 
65
  numeric_columns.append(col)
66
  except:
67
  pass
 
68
  if not numeric_columns:
69
+ raise ValueError("CSV檔案中未找到有效的數值欄位")
 
70
  return df, numeric_columns
71
  except Exception as e:
72
  st.error(f"數據加載錯誤:{str(e)}")
73
  return None, None
74
 
75
+ # ============================
76
+ # 生成雷達圖
77
+ # ============================
78
+
79
  def create_radar_chart(df, selected_rows, selected_columns, student_name=""):
80
+ """生成雷達圖 (包含圖例、極座標軸等設定)"""
81
  fig = go.Figure()
82
  line_styles = ['solid', 'dot', 'dash', 'longdash', 'dashdot']
83
  colors = ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728', '#9467BD']
 
133
  )
134
  return fig
135
 
136
+ # ============================
137
+ # 生成圖片
138
+ # ============================
139
+
140
  def generate_radar_image(fig):
141
+ """生成圖片 (重設 Kaleido 配置與更新字型設定)"""
142
  try:
143
  # 重設 kaleido 配置(含 extra_fonts)
144
  pio.kaleido.scope.default_font = CHINESE_FONT
 
187
  st.error(f"圖片生成失敗: {str(e)}")
188
  return None
189
 
190
+ # ============================
191
+ # 主程式
192
+ # ============================
193
+
194
  def main():
195
  st.title('學生成績雷達圖產生器')
196
  st.markdown("""
 
205
  </style>
206
  """, unsafe_allow_html=True)
207
 
208
+ setup_chinese_font() # 檢查中文字型
209
 
210
  uploaded_file = st.file_uploader("上傳CSV檔案", type=['csv'])
211
  if uploaded_file is not None:
 
242
  target_students = [s for s in all_students if s not in current_comparison]
243
  for idx, student in enumerate(target_students):
244
  try:
245
+ # 動態組合比較組(比較基準加上當前學生)
246
  fig = create_radar_chart(
247
  df,
248
  current_comparison + [student],
 
254
  image_bytes[student] = img
255
  except Exception as e:
256
  st.error(f"生成 {student} 圖表失敗:{str(e)}")
257
+ progress_bar.progress((idx + 1) / len(target_students))
258
  if image_bytes:
259
+ st.write("### 圖表預覽")
260
+ cols = st.columns(3)
261
+ for i, (student, img) in enumerate(image_bytes.items()):
262
+ with cols[i % 3]:
263
+ st.image(img, use_container_width=True)
264
+ st.caption(f"{student} 比較圖")
265
  zip_buffer = BytesIO()
266
  with ZipFile(zip_buffer, "w") as zip_file:
267
  for student, img in image_bytes.items():
 
276
  )
277
 
278
  if __name__ == "__main__":
279
+ main()