"""資料分析:讀取公開資料,查詢各縣市學生人數。""" import csv from pathlib import Path DATA_FILE = Path("data/students_by_county.csv") SAMPLE_YEAR = "114" SAMPLE_FIELD = "國小[人]" def load_rows(path=DATA_FILE): """讀取 CSV;utf-8-sig 也能正確處理政府資料常見的 BOM。""" with open(path, encoding="utf-8-sig", newline="") as file: return list(csv.DictReader(file)) def parse_count(value): """將有人數的欄位轉成整數;空白或非數字代表未知,不當成 0。""" cleaned = (value or "").strip().replace(",", "") if not cleaned or cleaned == "-": return None try: return int(cleaned) except ValueError: return None def count_by_county(rows, school_year, field): """依學年度篩選,再回傳各縣市的人數排序。""" totals = {} for row in rows: if row.get("學年度", "").strip() != str(school_year): continue count = parse_count(row.get(field)) county = row.get("縣市別", "").strip() if county and count is not None: totals[county] = count return sorted(totals.items(), key=lambda item: item[1], reverse=True) def get_count(rows, school_year, county, field): """取得指定學年度、縣市及欄位的人數;找不到時回傳 None。""" for row in rows: if row.get("學年度", "").strip() != str(school_year): continue if row.get("縣市別", "").strip() == county: return parse_count(row.get(field)) return None def print_text_chart(results, limit=8): """在 Console 印出簡單長條圖,讓每筆數字都能被核對。""" if not results: print("沒有符合條件的資料,請檢查學年度和欄位名稱。") return visible = results[:limit] largest = max(value for _, value in visible) print("縣市 人數 | 比例長條") for county, value in visible: bar_length = round(value / largest * 24) if largest else 0 print(f"{county:<6} {value:>8,} | {'█' * bar_length}") def main(): rows = load_rows() fields = list(rows[0]) if rows else [] print("=== 資料分析:縣市學生人數 ===") print(f"讀入 {len(rows)} 列資料") print(f"欄位:{', '.join(fields)}") print() # 範例問題:114 學年度,哪些縣市的國小學生人數最多? question = f"{SAMPLE_YEAR} 學年度,哪些縣市的 {SAMPLE_FIELD} 最多?" results = count_by_county(rows, SAMPLE_YEAR, SAMPLE_FIELD) print(f"範例問題:{question}") print_text_chart(results) # 你的下一步:換一個學年度、教育階段或可比較的欄位, # 先寫下預測,再執行並核對其中一筆原始資料。 if __name__ == "__main__": main()