Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -104,25 +104,7 @@ class SurveyAnalyzer:
|
|
104 |
}
|
105 |
}
|
106 |
|
107 |
-
|
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({
|
115 |
-
'滿意度項目': self.satisfaction_short_names,
|
116 |
-
'平均分數': satisfaction_means,
|
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',
|
@@ -189,10 +171,54 @@ class SurveyAnalyzer:
|
|
189 |
|
190 |
# 🎨 Streamlit UI
|
191 |
def main():
|
192 |
-
st.set_page_config(
|
|
|
|
|
|
|
|
|
193 |
|
194 |
-
|
195 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
|
197 |
# 讀取數據
|
198 |
df = read_google_sheet(sheet_id, gid)
|
@@ -200,26 +226,64 @@ def main():
|
|
200 |
if df is not None:
|
201 |
analyzer = SurveyAnalyzer()
|
202 |
|
203 |
-
#
|
204 |
-
|
|
|
|
|
|
|
|
|
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 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
|
215 |
-
#
|
216 |
if '月份' in df.columns:
|
217 |
months = ['全部'] + sorted(df['月份'].unique().tolist())
|
218 |
-
selected_month = st.sidebar.selectbox("選擇月份", months)
|
219 |
else:
|
220 |
# 如果沒有月份欄位,可以創建虛擬月份選項
|
221 |
-
|
222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
# 📌 基本統計數據
|
225 |
st.sidebar.header("📌 選擇數據分析")
|
|
|
104 |
}
|
105 |
}
|
106 |
|
107 |
+
標準差',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
title='📊 各項滿意度平均分數與標準差',
|
109 |
color='平均分數',
|
110 |
color_continuous_scale='Viridis',
|
|
|
171 |
|
172 |
# 🎨 Streamlit UI
|
173 |
def main():
|
174 |
+
st.set_page_config(
|
175 |
+
page_title="數位示範場域問卷調查分析",
|
176 |
+
layout="wide",
|
177 |
+
initial_sidebar_state="expanded"
|
178 |
+
)
|
179 |
|
180 |
+
# 自定義CSS樣式
|
181 |
+
st.markdown("""
|
182 |
+
<style>
|
183 |
+
.main-header {
|
184 |
+
font-size: 42px;
|
185 |
+
font-weight: bold;
|
186 |
+
color: #1E88E5;
|
187 |
+
text-align: center;
|
188 |
+
margin-bottom: 10px;
|
189 |
+
padding-bottom: 15px;
|
190 |
+
border-bottom: 2px solid #e0e0e0;
|
191 |
+
}
|
192 |
+
.sub-header {
|
193 |
+
font-size: 24px;
|
194 |
+
color: #424242;
|
195 |
+
text-align: center;
|
196 |
+
margin-bottom: 30px;
|
197 |
+
}
|
198 |
+
.unit-name {
|
199 |
+
font-size: 28px;
|
200 |
+
font-weight: bold;
|
201 |
+
color: #1565C0;
|
202 |
+
text-align: center;
|
203 |
+
padding: 10px;
|
204 |
+
background-color: #E3F2FD;
|
205 |
+
border-radius: 8px;
|
206 |
+
margin: 20px 0;
|
207 |
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
208 |
+
}
|
209 |
+
.card {
|
210 |
+
padding: 20px;
|
211 |
+
border-radius: 10px;
|
212 |
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
213 |
+
margin-bottom: 20px;
|
214 |
+
background-color: white;
|
215 |
+
}
|
216 |
+
</style>
|
217 |
+
""", unsafe_allow_html=True)
|
218 |
+
|
219 |
+
# 主標題與副標題
|
220 |
+
st.markdown('<div class="main-header">📊 數位示範場域問卷調查分析報告</div>', unsafe_allow_html=True)
|
221 |
+
st.markdown('<div class="sub-header">本報告提供全面的問卷調查分析與視覺化圖表,協助了解民眾滿意度與使用者特性</div>', unsafe_allow_html=True)
|
222 |
|
223 |
# 讀取數據
|
224 |
df = read_google_sheet(sheet_id, gid)
|
|
|
226 |
if df is not None:
|
227 |
analyzer = SurveyAnalyzer()
|
228 |
|
229 |
+
# 設置單位名稱(假設有「單位名稱」欄位,若無則顯示預設值)
|
230 |
+
unit_name = "數位示範場域滿意度調查中心"
|
231 |
+
if '單位名稱' in df.columns and not df['單位名稱'].isnull().all():
|
232 |
+
unit_names = df['單位名稱'].unique()
|
233 |
+
if len(unit_names) == 1:
|
234 |
+
unit_name = unit_names[0]
|
235 |
|
236 |
+
# 顯示單位名稱
|
237 |
+
st.markdown(f'<div class="unit-name">{unit_name}</div>', unsafe_allow_html=True)
|
238 |
+
|
239 |
+
# 新增場域和月份篩選器(使用更美觀的設計)
|
240 |
+
st.sidebar.markdown("### 🔍 **數據篩選**")
|
241 |
+
st.sidebar.markdown("---")
|
242 |
+
|
243 |
+
# 場域選擇
|
244 |
if '場域名稱' in df.columns:
|
245 |
venues = ['全部'] + sorted(df['場域名稱'].unique().tolist())
|
|
|
246 |
else:
|
247 |
# 如果沒有場域欄位,創建10個虛擬場域供選擇
|
248 |
+
venue_names = [
|
249 |
+
"臺北數位樂學園", "新北創新學院", "桃園智慧中心",
|
250 |
+
"臺中數位學苑", "臺南創客基地", "高雄創新園區",
|
251 |
+
"宜蘭數位中心", "花蓮創新基地", "臺東學習中心", "金門數位樂園"
|
252 |
+
]
|
253 |
+
venues = ['全部'] + venue_names
|
254 |
+
|
255 |
+
selected_venues = st.sidebar.multiselect(
|
256 |
+
"📍 **選擇場域**",
|
257 |
+
venues,
|
258 |
+
default=['全部'],
|
259 |
+
help="可選擇多個場域進行數據分析比較"
|
260 |
+
)
|
261 |
|
262 |
+
# 月份選擇
|
263 |
if '月份' in df.columns:
|
264 |
months = ['全部'] + sorted(df['月份'].unique().tolist())
|
|
|
265 |
else:
|
266 |
# 如果沒有月份欄位,可以創建虛擬月份選項
|
267 |
+
current_year = datetime.now().year
|
268 |
+
months = ['全部'] + [f'{current_year}年{i+1}月' for i in range(12)]
|
269 |
+
|
270 |
+
selected_month = st.sidebar.selectbox(
|
271 |
+
"📅 **選擇月份**",
|
272 |
+
months,
|
273 |
+
help="選擇特定月份查看數據趨勢"
|
274 |
+
)
|
275 |
+
|
276 |
+
# 年齡區間篩選
|
277 |
+
st.sidebar.markdown("### 📊 **年齡區間篩選**")
|
278 |
+
ages = analyzer.calculate_age(df['2.出生年(民國__年)'])
|
279 |
+
min_age, max_age = int(ages.min()), int(ages.max())
|
280 |
+
age_range = st.sidebar.slider(
|
281 |
+
"選擇年齡範圍",
|
282 |
+
min_age,
|
283 |
+
max_age,
|
284 |
+
(min_age, max_age),
|
285 |
+
help="拖曳調整以篩選特定年齡區間的受訪者"
|
286 |
+
)
|
287 |
|
288 |
# 📌 基本統計數據
|
289 |
st.sidebar.header("📌 選擇數據分析")
|