題變成結(jié)構(gòu)化數(shù)據(jù):統(tǒng)計(jì)與可視化實(shí)戰(zhàn))
歐洲超級杯巴黎 2-1 維拉K77 克瓦拉茨赫利亞和杜埃先后破門登貝萊替補(bǔ)登場送出助攻。這條新聞標(biāo)題在球迷眼里是比賽結(jié)果在開發(fā)者眼里卻是一個(gè)典型的數(shù)據(jù)建模場景比分、進(jìn)球者、助攻者、替補(bǔ)登場四個(gè)信息分別對應(yīng)不同的數(shù)據(jù)字段和事件類型。文章以這場比賽為案例不討論戰(zhàn)術(shù)和判罰只講一件事如何用 Python 把一場比賽從一句話標(biāo)題整理成結(jié)構(gòu)化數(shù)據(jù)并完成進(jìn)球貢獻(xiàn)統(tǒng)計(jì)、替補(bǔ)效應(yīng)量化和比賽時(shí)間線可視化。下面給出完整代碼、數(shù)據(jù)文件和分析腳本讀者可以在本地環(huán)境直接跑通再替換成自己關(guān)注的比賽數(shù)據(jù)。這篇文章適合兩類讀者。一類是剛接觸數(shù)據(jù)分析、想用真實(shí)場景練手的開發(fā)者另一類是足球內(nèi)容創(chuàng)作者或數(shù)據(jù)愛好者希望把比賽報(bào)道改造成可復(fù)用的數(shù)據(jù)模板。閱讀前只需要有 Python 基礎(chǔ)了解變量、函數(shù)和 JSON 即可。整條技術(shù)主線是先確定比賽數(shù)據(jù)的字段和數(shù)據(jù)模型再準(zhǔn)備環(huán)境然后用 dataclass 建模接著把巴黎 2-1 維拉寫入 JSON 并加載最后完成統(tǒng)計(jì)與可視化并補(bǔ)齊常見坑和擴(kuò)展方向。1. 先想清楚一場比賽的數(shù)據(jù)要從哪些維度描述1.1 新聞標(biāo)題是人讀的統(tǒng)計(jì)系統(tǒng)需要字段和事件“歐洲超級杯巴黎 2-1 維拉K77 杜埃破門登貝萊替補(bǔ)送助”這句話里面至少包含四層信息比賽名稱歐洲超級杯。對陣與比分巴黎 2-1 維拉。進(jìn)球球員K77、杜埃。替補(bǔ)與助攻登貝萊替補(bǔ)登場并送出助攻。如果直接把這串文字存到數(shù)據(jù)庫里檢索時(shí)只能做模糊匹配無法回答“登貝萊的替補(bǔ)登場是否直接改變了比賽結(jié)果”“杜埃的進(jìn)球發(fā)生在第幾分鐘”這類問題。所以第一步是把信息拆成字段再根據(jù)字段之間的關(guān)系設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)。信息標(biāo)題中的表述對應(yīng)字段是否需要單獨(dú)事件比賽名稱歐洲超級杯name否對陣雙方巴黎 / 維拉h(huán)ome_team / away_team否比分2-1home_score / away_score否但需要進(jìn)球事件支撐進(jìn)球者K77、杜埃goal 事件的 player 字段是替補(bǔ)登場登貝萊替補(bǔ)substitution 事件的 player 字段是助攻登貝萊送助goal 事件的 related_player 字段由 goal 事件承擔(dān)比賽名稱、對陣和比分是比賽級別的屬性只保存一次即可。進(jìn)球者和替補(bǔ)登場必須用事件來描述因?yàn)橥幻騿T可以在多個(gè)事件里出現(xiàn)而且事件自帶“第幾分鐘發(fā)生”這個(gè)時(shí)間維度。1.2 事件數(shù)據(jù)進(jìn)球、替補(bǔ)、助攻如何組織足球比賽本質(zhì)上是按時(shí)間排序的事件流。本文只需要三類事件但實(shí)際項(xiàng)目中至少要知道它們各自的組織方式goal 事件記錄進(jìn)球方、進(jìn)球者、分鐘、助攻者、當(dāng)時(shí)比分。substitution 事件記錄登場球員、被換下球員、分鐘。assist 信息建議合并進(jìn) goal 事件用 related_player 字段表示不需要單獨(dú)建事件。助攻之所以不建議拆成獨(dú)立事件是因?yàn)橹ズ瓦M(jìn)球在業(yè)務(wù)上是一對一關(guān)聯(lián)。拆成兩個(gè)事件后統(tǒng)計(jì)“某球員的參與進(jìn)球數(shù)”時(shí)還要做一次關(guān)聯(lián)查詢徒增復(fù)雜度。合并進(jìn) goal 事件后一次循環(huán)就能同時(shí)統(tǒng)計(jì)進(jìn)球和助攻。事件類型必填字段典型取值說明goalevent_type, team, minute, playergoal, home, 23, 克瓦拉茨赫利亞(K77)player 是進(jìn)球者related_player 可存助攻者substitutionevent_type, team, minute, player, related_playersubstitution, home, 46, 登貝萊, 被換下球員player 是登場球員related_player 是離場球員1.3 本文的最小技術(shù)閉環(huán)從這場比賽出發(fā)代碼要完成五個(gè)動作加載 JSON、校驗(yàn)比分、統(tǒng)計(jì)進(jìn)球和助攻、計(jì)算替補(bǔ)登場時(shí)間、畫時(shí)間線和貢獻(xiàn)圖。數(shù)據(jù)規(guī)模小用 Python 自帶的 dataclass 加 pandas、matplotlib 就足夠不需要引入 Spark、Flink 之類的大數(shù)據(jù)組件。2. 環(huán)境準(zhǔn)備Python 版本與依賴庫2.1 版本和依賴本文代碼使用 Python 3.10 及以上版本主要因?yàn)?dataclass 和類型注解在 3.10 上已經(jīng)非常成熟。依賴庫只有三個(gè)安裝成本很低。依賴用途建議版本Python運(yùn)行環(huán)境3.10pandas表格統(tǒng)計(jì)與聚合2.xmatplotlib圖表繪制3.8numpy數(shù)值計(jì)算pandas 依賴1.26在項(xiàng)目目錄下創(chuàng)建 requirements.txtpandas2.0 matplotlib3.8 numpy1.26pandas 不是必須的只做單場比賽統(tǒng)計(jì)時(shí)用純 Python 字典也夠。但文章后面會把“多場比賽、多名球員”的聚合作為擴(kuò)展方向pandas 的 groupby 能力在數(shù)據(jù)量變大后會顯著減少代碼量所以這里直接引入。2.2 創(chuàng)建虛擬環(huán)境并安裝建議先建虛擬環(huán)境避免污染系統(tǒng) Pythonmkdir match_analysis cd match_analysis python -m venv .venv # Windows .venv\Scripts\activate # macOS / Linux source .venv/bin/activate pip install -r requirements.txt安裝完成后驗(yàn)證版本python -c import pandas, matplotlib; print(pandas.__