Rooobert commited on
Commit
fffa948
·
verified ·
1 Parent(s): 1d22655

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -353
app.py CHANGED
@@ -104,25 +104,11 @@ class SurveyAnalyzer:
104
  }
105
  }
106
 
107
- def plot_satisfaction_scores(self, df: pd.DataFrame, venues=None, month=None, age_range=None):
108
- """📊 各項滿意度平均分數圖表 - 美化版"""
109
- # 過濾數據
110
- filtered_df = df.copy()
111
- if venues and '全部' not in venues:
112
- filtered_df = filtered_df[filtered_df['場域名稱'].isin(venues)]
113
- if month and month != '全部':
114
- # 假設有一個月份欄位,如果沒有請調整
115
- filtered_df = filtered_df[filtered_df['月份'] == month]
116
-
117
- # 年齡篩選
118
- if age_range:
119
- ages = self.calculate_age(filtered_df['2.出生年(民國__年)'])
120
- age_mask = (ages >= age_range[0]) & (ages <= age_range[1])
121
- filtered_df = filtered_df[age_mask]
122
-
123
- # 計算過濾後數據的平均和標準差
124
- satisfaction_means = [filtered_df[col].mean() for col in self.satisfaction_columns]
125
- satisfaction_stds = [filtered_df[col].std() for col in self.satisfaction_columns]
126
 
127
  # 創建數據框
128
  satisfaction_df = pd.DataFrame({
@@ -131,96 +117,37 @@ class SurveyAnalyzer:
131
  '標準差': satisfaction_stds
132
  })
133
 
134
- # 排序結果(可選)
135
- satisfaction_df = satisfaction_df.sort_values(by='平均分數', ascending=False)
136
-
137
- # 建立顏色漸變映射
138
- color_scale = [
139
- [0, '#90CAF9'], # 淺藍色
140
- [0.5, '#2196F3'], # 中藍色
141
- [1, '#1565C0'] # 深藍色
142
- ]
143
-
144
  # 繪製條形圖
145
  fig = px.bar(
146
  satisfaction_df,
147
  x='滿意度項目',
148
  y='平均分數',
149
  error_y='標準差',
150
- title='📊 各項滿意度平均分數與標準差分析',
151
  color='平均分數',
152
- color_continuous_scale=color_scale,
153
- text='平均分數',
154
- hover_data={
155
- '滿意度項目': True,
156
- '平均分數': ':.2f',
157
- '標準差': ':.2f'
158
- }
159
  )
160
 
161
  # 調整圖表佈局
162
  fig.update_layout(
163
- font=dict(family="Arial", size=16),
164
- title_font=dict(family="Arial Black", size=24),
165
- title_x=0.5, # 標題置中
166
  xaxis_title="滿意度項目",
167
  yaxis_title="平均分數",
168
- yaxis_range=[0, 5], # 評分範圍從0開始,視覺上更明顯
169
- plot_bgcolor='rgba(240,240,240,0.8)', # 淺灰色背景
170
- paper_bgcolor='white',
171
- xaxis_tickangle=-25, # 斜角標籤,避免重疊
172
- margin=dict(l=40, r=40, t=80, b=60),
173
- legend_title_text="平均分數",
174
- shapes=[
175
- # 添加參考線 - 例如4分
176
- dict(
177
- type='line',
178
- yref='y', y0=4, y1=4,
179
- xref='paper', x0=0, x1=1,
180
- line=dict(color='rgba(220,20,60,0.5)', width=2, dash='dash')
181
- )
182
- ],
183
- annotations=[
184
- # 參考線標籤
185
- dict(
186
- x=0.02, y=4.1,
187
- xref='paper', yref='y',
188
- text='優良標準 (4分)',
189
- showarrow=False,
190
- font=dict(size=14, color='rgba(220,20,60,0.8)')
191
- )
192
- ]
193
  )
194
 
195
  # 調整文字格式
196
  fig.update_traces(
197
  texttemplate='%{y:.2f}',
198
- textposition='outside',
199
- marker_line_color='rgb(8,48,107)',
200
- marker_line_width=1.5,
201
- opacity=0.85
202
- )
203
-
204
- # 添加受訪人數標註
205
- num_respondents = len(filtered_df)
206
- fig.add_annotation(
207
- x=0.5,
208
- xref='paper',
209
- yref='paper',
210
- text=f'受訪人數: {num_respondents}人',
211
- showarrow=False,
212
- font=dict(size=16),
213
- bgcolor='rgba(255,255,255,0.8)',
214
- bordercolor='rgba(0,0,0,0.2)',
215
- borderwidth=1,
216
- borderpad=4,
217
- y=-0.2
218
  )
219
 
220
  st.plotly_chart(fig, use_container_width=True)
221
 
222
- def plot_gender_distribution(self, df: pd.DataFrame, venues=None, month=None, age_range=None):
223
- """🟠 性別���佈圓餅圖 - 增強精緻版"""
224
  # 過濾數據
225
  filtered_df = df.copy()
226
  if venues and '全部' not in venues:
@@ -229,13 +156,6 @@ class SurveyAnalyzer:
229
  # 假設有一個月份欄位,如果沒有請調整
230
  filtered_df = filtered_df[filtered_df['月份'] == month]
231
 
232
- # 年齡篩選
233
- if age_range:
234
- ages = self.calculate_age(filtered_df['2.出生年(民國__年)'])
235
- age_mask = (ages >= age_range[0]) & (ages <= age_range[1])
236
- filtered_df = filtered_df[age_mask]
237
-
238
- # 取得性別資料
239
  gender_counts = filtered_df['1. 性別'].value_counts().reset_index()
240
  gender_counts.columns = ['性別', '人數']
241
 
@@ -244,27 +164,14 @@ class SurveyAnalyzer:
244
  gender_counts['百分比'] = (gender_counts['人數'] / total * 100).round(1)
245
  gender_counts['標籤'] = gender_counts.apply(lambda x: f"{x['性別']}: {x['人數']}人 ({x['百分比']}%)", axis=1)
246
 
247
- # 獲取篩選條件說明
248
- filter_description = []
249
- if venues and '全部' not in venues:
250
- filter_description.append(f"場域: {', '.join(venues)}")
251
- if month and month != '全部':
252
- filter_description.append(f"月份: {month}")
253
- if age_range and (age_range[0] != min(self.calculate_age(df['2.出生年(民國__年)'])) or
254
- age_range[1] != max(self.calculate_age(df['2.出生年(民國__年)']))):
255
- filter_description.append(f"年齡: {age_range[0]}-{age_range[1]}歲")
256
-
257
- filter_text = "(" + ", ".join(filter_description) + ")" if filter_description else ""
258
 
259
- # 設定顏色映射 - 男性藍色,女性紅色 - 使用更精緻的顏色
260
- color_map = {'男性': '#1976D2', '女性': '#D32F2F'}
261
-
262
- # 建立子圖佈局以添加更多自定義元素
263
  fig = px.pie(
264
  gender_counts,
265
  names='性別',
266
  values='人數',
267
- title=f'👥 受訪者性別分布{filter_text}',
268
  color='性別',
269
  color_discrete_map=color_map,
270
  hover_data=['人數', '百分比'],
@@ -272,144 +179,20 @@ class SurveyAnalyzer:
272
  custom_data=['標籤']
273
  )
274
 
275
- # 更新圖表佈局
276
- fig.update_layout(
277
- font=dict(family="Arial", size=16),
278
- title_font=dict(family="Arial Black", size=24),
279
- title_x=0.5, # 標題置中
280
- legend_title_text="性別",
281
- legend=dict(
282
- orientation="h",
283
- yanchor="bottom",
284
- y=-0.2,
285
- xanchor="center",
286
- x=0.5,
287
- font=dict(size=16),
288
- bordercolor="#E0E0E0",
289
- borderwidth=2
290
- ),
291
- margin=dict(l=20, r=20, t=80, b=100),
292
- paper_bgcolor='white',
293
- annotations=[
294
- dict(
295
- text=f"總受訪人數: {total}人",
296
- x=0.5, y=-0.3,
297
- xref="paper",
298
- yref="paper",
299
- showarrow=False,
300
- font=dict(size=16, color="#616161")
301
- )
302
- ]
303
- )
304
-
305
- # 添加男女比例標籤
306
- male_count = gender_counts.loc[gender_counts['性別'] == '男性', '人數'].values[0] if '男性' in gender_counts['性別'].values else 0
307
- female_count = gender_counts.loc[gender_counts['性別'] == '女性', '人數'].values[0] if '女性' in gender_counts['性別'].values else 0
308
-
309
- # 計算男女比例
310
- if male_count > 0 and female_count > 0:
311
- ratio = round(male_count / female_count, 2)
312
- ratio_text = f"男女比例 = {ratio}:1"
313
- elif male_count > 0 and female_count == 0:
314
- ratio_text = "僅有男性"
315
- elif female_count > 0 and male_count == 0:
316
- ratio_text = "僅有女性"
317
- else:
318
- ratio_text = "無性別數據"
319
-
320
- fig.add_annotation(
321
- text=ratio_text,
322
- x=0.5, y=-0.15,
323
- xref="paper",
324
- yref="paper",
325
- showarrow=False,
326
- font=dict(size=16, color="#424242", family="Arial Bold")
327
- )
328
-
329
- # 更新懸停資訊
330
  fig.update_traces(
331
  textinfo='percent+label',
332
- hovertemplate='%{customdata[0]}',
333
- textfont_size=16,
334
- marker=dict(line=dict(color='#FFFFFF', width=2)),
335
- pull=[0.03, 0.03], # 稍微分離餅圖片段
336
- rotation=45 # 旋轉角度
337
  )
338
 
339
  st.plotly_chart(fig, use_container_width=True)
340
-
341
- # 在圓餅圖下方添加簡單分析
342
- st.markdown("""
343
- <div style="background-color:#F5F5F5; padding:15px; border-radius:10px; margin-top:10px; border-left:5px solid #1976D2;">
344
- <h4 style="color:#1976D2;">📊 性別分佈簡易分析</h4>
345
- """, unsafe_allow_html=True)
346
-
347
- # 生成簡單分析文字
348
- if total > 0:
349
- majority_gender = '男性' if male_count > female_count else '女性' if female_count > male_count else '男女相等'
350
- majority_pct = max(male_count, female_count) / total * 100 if male_count != female_count else 50
351
-
352
- if male_count != female_count:
353
- st.markdown(f"""
354
- <p>本次調查中,<strong>{majority_gender}</strong>佔多數,約佔總體的<strong>{majority_pct:.1f}%</strong>。</p>
355
- """, unsafe_allow_html=True)
356
- else:
357
- st.markdown("<p>本次調查中,男女比例相等,各佔50%。</p>", unsafe_allow_html=True)
358
- else:
359
- st.markdown("<p>目前沒有足夠的性別數據進行分析。</p>", unsafe_allow_html=True)
360
-
361
- st.markdown("</div>", unsafe_allow_html=True)
362
 
363
  # 🎨 Streamlit UI
364
  def main():
365
- st.set_page_config(
366
- page_title="數位示範場域問卷調查分析",
367
- layout="wide",
368
- initial_sidebar_state="expanded"
369
- )
370
 
371
- # 自定義CSS樣式
372
- st.markdown("""
373
- <style>
374
- .main-header {
375
- font-size: 42px;
376
- font-weight: bold;
377
- color: #1E88E5;
378
- text-align: center;
379
- margin-bottom: 10px;
380
- padding-bottom: 15px;
381
- border-bottom: 2px solid #e0e0e0;
382
- }
383
- .sub-header {
384
- font-size: 24px;
385
- color: #424242;
386
- text-align: center;
387
- margin-bottom: 30px;
388
- }
389
- .unit-name {
390
- font-size: 28px;
391
- font-weight: bold;
392
- color: #1565C0;
393
- text-align: center;
394
- padding: 10px;
395
- background-color: #E3F2FD;
396
- border-radius: 8px;
397
- margin: 20px 0;
398
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
399
- }
400
- .card {
401
- padding: 20px;
402
- border-radius: 10px;
403
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
404
- margin-bottom: 20px;
405
- background-color: white;
406
- }
407
- </style>
408
- """, unsafe_allow_html=True)
409
-
410
- # 主標題與副標題
411
- st.markdown('<div class="main-header">📊 數位示範場域問卷調查分析報告</div>', unsafe_allow_html=True)
412
- st.markdown('<div class="sub-header">本報告提供全面的問卷調查分析與視覺化圖表,協助了解民眾滿意度與使用者特性</div>', unsafe_allow_html=True)
413
 
414
  # 讀取數據
415
  df = read_google_sheet(sheet_id, gid)
@@ -417,137 +200,52 @@ def main():
417
  if df is not None:
418
  analyzer = SurveyAnalyzer()
419
 
420
- # 設置單位名稱(假設有「單位名稱」欄位,若無則顯示預設值)
421
- unit_name = "數位示範場域滿意度調查中心"
422
- if '單位名稱' in df.columns and not df['單位名稱'].isnull().all():
423
- unit_names = df['單位名稱'].unique()
424
- if len(unit_names) == 1:
425
- unit_name = unit_names[0]
426
-
427
- # 顯示單位名稱
428
- st.markdown(f'<div class="unit-name">{unit_name}</div>', unsafe_allow_html=True)
429
-
430
- # 新增場域和月份篩選器(使用更美觀的設計)
431
- st.sidebar.markdown("### 🔍 **數據篩選**")
432
- st.sidebar.markdown("---")
433
 
434
- # 場域選擇
435
  if '場域名稱' in df.columns:
436
  venues = ['全部'] + sorted(df['場域名稱'].unique().tolist())
 
437
  else:
438
  # 如果沒有場域欄位,創建10個虛擬場域供選擇
439
- venue_names = [
440
- "臺北數位樂學園", "新北創新學院", "桃園智慧中心",
441
- "臺中數位學苑", "臺南創客基地", "高雄創新園區",
442
- "宜蘭數位中心", "花蓮創新基地", "臺東學習中心", "金門數位樂園"
443
- ]
444
- venues = ['全部'] + venue_names
445
 
446
- selected_venues = st.sidebar.multiselect(
447
- "📍 **選擇場域**",
448
- venues,
449
- default=['全部'],
450
- help="可選擇多個場域進行數據分析比較"
451
- )
452
-
453
- # 月份選擇
454
  if '月份' in df.columns:
455
  months = ['全部'] + sorted(df['月份'].unique().tolist())
 
456
  else:
457
  # 如果沒有月份欄位,可以創建虛擬月份選項
458
- current_year = datetime.now().year
459
- months = ['全部'] + [f'{current_year}年{i+1}月' for i in range(12)]
460
-
461
- selected_month = st.sidebar.selectbox(
462
- "📅 **選擇月份**",
463
- months,
464
- help="選擇特定月份查看數據趨勢"
465
- )
466
-
467
- # 年齡區間篩選
468
- st.sidebar.markdown("### 📊 **年齡區間篩選**")
469
- ages = analyzer.calculate_age(df['2.出生年(民國__年)'])
470
- min_age, max_age = int(ages.min()), int(ages.max())
471
- age_range = st.sidebar.slider(
472
- "選擇年齡範圍",
473
- min_age,
474
- max_age,
475
- (min_age, max_age),
476
- help="拖曳調整以篩選特定年齡區間的受訪者"
477
- )
478
 
479
  # 📌 基本統計數據
480
  st.sidebar.header("📌 選擇數據分析")
481
  selected_analysis = st.sidebar.radio("選擇要查看的分析",
482
  ["📋 問卷統計報告", "📊 滿意度統計", "🟠 性別分佈"])
483
 
484
- # 應用所有篩選條件
485
- filtered_df = df.copy()
486
- if selected_venues and '全部' not in selected_venues:
487
- if '場域名稱' in filtered_df.columns:
488
- filtered_df = filtered_df[filtered_df['場域名稱'].isin(selected_venues)]
489
- if selected_month and selected_month != '全部':
490
- if '月份' in filtered_df.columns:
491
- filtered_df = filtered_df[filtered_df['月份'] == selected_month]
492
-
493
- # 年齡篩選
494
- if age_range:
495
- ages = analyzer.calculate_age(filtered_df['2.出生年(民國__年)'])
496
- age_mask = (ages >= age_range[0]) & (ages <= age_range[1])
497
- filtered_df = filtered_df[age_mask]
498
-
499
- # 顯示當前選擇的篩選器
500
- filter_status = []
501
- if selected_venues and '全部' not in selected_venues:
502
- filter_status.append(f"📍 場域: {', '.join(selected_venues)}")
503
- if selected_month and selected_month != '全部':
504
- filter_status.append(f"📅 月份: {selected_month}")
505
- if age_range and (age_range[0] != min(analyzer.calculate_age(df['2.出生年(民國__年)'])) or
506
- age_range[1] != max(analyzer.calculate_age(df['2.出生年(民國__年)']))):
507
- filter_status.append(f"👥 年齡: {age_range[0]}-{age_range[1]}歲")
508
-
509
- if filter_status:
510
- st.markdown("""
511
- <div style="background-color:#E3F2FD; padding:10px; border-radius:8px; margin-bottom:20px; border-left:4px solid #1976D2;">
512
- <h4 style="margin-bottom:10px; color:#1565C0;">🔍 當前篩選條件</h4>
513
- """, unsafe_allow_html=True)
514
-
515
- for status in filter_status:
516
- st.markdown(f"<p style='margin:5px 0;'>{status}</p>", unsafe_allow_html=True)
517
-
518
- # 顯示篩選後的樣本數
519
- st.markdown(f"""
520
- <p style='margin-top:10px; font-weight:bold;'>📊 篩選後樣本數: {len(filtered_df)}人</p>
521
- </div>
522
- """, unsafe_allow_html=True)
523
-
524
- # 數據分析區塊
525
  if selected_analysis == "📋 問卷統計報告":
526
- st.markdown('<h2 style="color:#1976D2;">📋 問卷統計報告</h2>', unsafe_allow_html=True)
527
-
528
- # 生成目前篩選條件下的報告
529
- report = analyzer.generate_report(filtered_df)
530
-
531
- # 使用卡片樣式顯示統計信息
532
- col1, col2 = st.columns(2)
533
-
534
- with col1:
535
- st.markdown('<div class="card">', unsafe_allow_html=True)
536
- st.markdown('<h3 style="color:#1976D2; border-bottom:1px solid #e0e0e0; padding-bottom:10px;">📊 基本統計數據</h3>', unsafe_allow_html=True)
537
-
538
- for key, value in report['基本統計'].items():
539
- if isinstance(value, dict):
540
- st.markdown(f"<p><strong>{key}:</strong></p>", unsafe_allow_html=True)
541
- for k, v in value.items():
542
- st.markdown(f"<p style='margin-left:20px;'>- {k}: {v}</p>", unsafe_allow_html=True)
543
- else:
544
- st.markdown(f"<p><strong>{key}:</strong> {value}</p>", unsafe_allow_html=True)
545
-
546
- st.markdown('</div>', unsafe_allow_html=True)
547
-
548
- with col2:
549
- st.markdown('<div class="card">', unsafe_allow_html=True)
550
- # Add the rest of the code here
551
 
552
  if __name__ == "__main__":
553
  main()
 
104
  }
105
  }
106
 
107
+ def plot_satisfaction_scores(self, df: pd.DataFrame):
108
+ """📊 各項滿意度平均分數圖表"""
109
+ # 準備數據
110
+ satisfaction_means = [df[col].mean() for col in self.satisfaction_columns]
111
+ satisfaction_stds = [df[col].std() for col in self.satisfaction_columns]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
  # 創建數據框
114
  satisfaction_df = pd.DataFrame({
 
117
  '標準差': satisfaction_stds
118
  })
119
 
 
 
 
 
 
 
 
 
 
 
120
  # 繪製條形圖
121
  fig = px.bar(
122
  satisfaction_df,
123
  x='滿意度項目',
124
  y='平均分數',
125
  error_y='標準差',
126
+ title='📊 各項滿意度平均分數與標準差',
127
  color='平均分數',
128
+ color_continuous_scale='Viridis',
129
+ text='平均分數'
 
 
 
 
 
130
  )
131
 
132
  # 調整圖表佈局
133
  fig.update_layout(
134
+ font=dict(size=16),
135
+ title_font=dict(size=24),
 
136
  xaxis_title="滿意度項目",
137
  yaxis_title="平均分數",
138
+ yaxis_range=[1, 5], # 假設評分範圍是 1-5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  )
140
 
141
  # 調整文字格式
142
  fig.update_traces(
143
  texttemplate='%{y:.2f}',
144
+ textposition='outside'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  )
146
 
147
  st.plotly_chart(fig, use_container_width=True)
148
 
149
+ def plot_gender_distribution(self, df: pd.DataFrame, venues=None, month=None):
150
+ """🟠 性別分佈圓餅圖(使用藍色和紅色)"""
151
  # 過濾數據
152
  filtered_df = df.copy()
153
  if venues and '全部' not in venues:
 
156
  # 假設有一個月份欄位,如果沒有請調整
157
  filtered_df = filtered_df[filtered_df['月份'] == month]
158
 
 
 
 
 
 
 
 
159
  gender_counts = filtered_df['1. 性別'].value_counts().reset_index()
160
  gender_counts.columns = ['性別', '人數']
161
 
 
164
  gender_counts['百分比'] = (gender_counts['人數'] / total * 100).round(1)
165
  gender_counts['標籤'] = gender_counts.apply(lambda x: f"{x['性別']}: {x['人數']}人 ({x['百分比']}%)", axis=1)
166
 
167
+ # 設定顏色映射 - 男性藍色,女性紅色
168
+ color_map = {'男性': '#2171b5', '女性': '#cb181d'}
 
 
 
 
 
 
 
 
 
169
 
 
 
 
 
170
  fig = px.pie(
171
  gender_counts,
172
  names='性別',
173
  values='人數',
174
+ title='🟠 受訪者性別分布',
175
  color='性別',
176
  color_discrete_map=color_map,
177
  hover_data=['人數', '百分比'],
 
179
  custom_data=['標籤']
180
  )
181
 
182
+ # 更新悬停信息
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  fig.update_traces(
184
  textinfo='percent+label',
185
+ hovertemplate='%{customdata[0]}'
 
 
 
 
186
  )
187
 
188
  st.plotly_chart(fig, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  # 🎨 Streamlit UI
191
  def main():
192
+ st.set_page_config(page_title="問卷調查分析", layout="wide")
 
 
 
 
193
 
194
+ st.title("📊 問卷調查分析報告")
195
+ st.write("本頁面展示問卷調查數據的分析結果,包括統計信息與視覺化圖表。")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
  # 讀取數據
198
  df = read_google_sheet(sheet_id, gid)
 
200
  if df is not None:
201
  analyzer = SurveyAnalyzer()
202
 
203
+ # 新增場域和月份篩選器
204
+ st.sidebar.header("🔍 數據篩選")
 
 
 
 
 
 
 
 
 
 
 
205
 
206
+ # 假設數據有「場域名稱」欄位,如果名稱不同請調整
207
  if '場域名稱' in df.columns:
208
  venues = ['全部'] + sorted(df['場域名稱'].unique().tolist())
209
+ selected_venues = st.sidebar.multiselect("選擇場域", venues, default=['全部'])
210
  else:
211
  # 如果沒有場域欄位,創建10個虛擬場域供選擇
212
+ venues = ['全部'] + [f'場域{i+1}' for i in range(10)]
213
+ selected_venues = st.sidebar.multiselect("選擇場域", venues, default=['全部'])
 
 
 
 
214
 
215
+ # 假設數據有「月份」欄位,如果沒有請調整
 
 
 
 
 
 
 
216
  if '月份' in df.columns:
217
  months = ['全部'] + sorted(df['月份'].unique().tolist())
218
+ selected_month = st.sidebar.selectbox("選擇月份", months)
219
  else:
220
  # 如果沒有月份欄位,可以創建虛擬月份選項
221
+ months = ['全部'] + [f'{i+1}月' for i in range(12)]
222
+ selected_month = st.sidebar.selectbox("選擇月份", months)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
  # 📌 基本統計數據
225
  st.sidebar.header("📌 選擇數據分析")
226
  selected_analysis = st.sidebar.radio("選擇要查看的分析",
227
  ["📋 問卷統計報告", "📊 滿意度統計", "🟠 性別分佈"])
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  if selected_analysis == "📋 問卷統計報告":
230
+ st.header("📋 問卷統計報告")
231
+ report = analyzer.generate_report(df)
232
+ for category, stats in report.items():
233
+ with st.expander(f"🔍 {category}", expanded=True):
234
+ for key, value in stats.items():
235
+ if key == '各項滿意度':
236
+ st.write(f"**{key}:**")
237
+ for item, item_stats in value.items():
238
+ st.write(f" - **{item}**: {', '.join([f'{k}: {v}' for k, v in item_stats.items()])}")
239
+ else:
240
+ st.write(f"**{key}**: {value}")
241
+
242
+ elif selected_analysis == "📊 滿意度統計":
243
+ st.header("📊 滿意度統計")
244
+ analyzer.plot_satisfaction_scores(df)
245
+
246
+ elif selected_analysis == "🟠 性別分佈":
247
+ st.header("🟠 性別分佈")
248
+ analyzer.plot_gender_distribution(df, selected_venues, selected_month)
 
 
 
 
 
 
249
 
250
  if __name__ == "__main__":
251
  main()