數(shù)據(jù)分析:從清洗到經(jīng)濟(jì)評(píng)估的完整實(shí)踐)
簡(jiǎn)介一份面向高校師生及Python初學(xué)者與數(shù)據(jù)分析學(xué)習(xí)者的校園消費(fèi)行為分析項(xiàng)目基于校園卡消費(fèi)數(shù)據(jù)完整實(shí)現(xiàn)從數(shù)據(jù)加載、預(yù)處理、特征工程到KMeans消費(fèi)聚類(lèi)、群體畫(huà)像與Plotly交互可視化的流程并借助Streamlit提供Web交互界面可輔助理解學(xué)生經(jīng)濟(jì)狀況與消費(fèi)規(guī)律。壓縮包共24個(gè)文件大小約13.06MB主要包含Python源碼、CSV樣例數(shù)據(jù)、Markdown運(yùn)行文檔、PDF與DOCX說(shuō)明報(bào)告以及pyc編譯文件、啟動(dòng)腳本和演示圖片各類(lèi)型分工明確便于對(duì)照學(xué)習(xí)與二次開(kāi)發(fā)。目前已有142人學(xué)習(xí)下載。資源覆蓋完整的項(xiàng)目結(jié)構(gòu)數(shù)據(jù)加載模塊支持多種編碼與合并預(yù)處理模塊完成異常過(guò)濾和時(shí)間特征提取模型模塊基于KMeans默認(rèn)劃分低中高三個(gè)消費(fèi)群可視化模塊生成消費(fèi)時(shí)段分布、食堂占比和三維聚類(lèi)圖另有說(shuō)明報(bào)告梳理方案細(xì)節(jié)適合用于課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)或數(shù)據(jù)挖掘入門(mén)實(shí)踐。1. 校園消費(fèi)行為分析與學(xué)生經(jīng)濟(jì)評(píng)估一張校園卡流水能算出什么一所三萬(wàn)人的高校一卡通系統(tǒng)每天產(chǎn)生幾十萬(wàn)條消費(fèi)流水。食堂、超市、開(kāi)水房、浴室、校醫(yī)院每筆記錄都帶著學(xué)號(hào)、時(shí)間、商戶(hù)、金額。這套數(shù)據(jù)表面上是后勤對(duì)賬的依據(jù)但換個(gè)視角它就是一份高頻更新的學(xué)生生活成本樣本。校園消費(fèi)行為分析做的事是把這些流水清洗成規(guī)范的結(jié)構(gòu)化數(shù)據(jù)再提取每名學(xué)生的消費(fèi)水平、消費(fèi)習(xí)慣和消費(fèi)結(jié)構(gòu)學(xué)生經(jīng)濟(jì)評(píng)估則是基于這些特征輔助判斷學(xué)生的實(shí)際經(jīng)濟(jì)狀況為資助評(píng)定、勤工助學(xué)崗位分配提供數(shù)據(jù)參考。項(xiàng)目資源里通常包含完整的 Python 源碼、脫敏后的校園消費(fèi)數(shù)據(jù)集、運(yùn)行文檔教程和說(shuō)明報(bào)告適合數(shù)據(jù)分析課程設(shè)計(jì)、高校信息化部門(mén)的數(shù)據(jù)挖掘?qū)嵺`以及想拿真實(shí)場(chǎng)景練手 Python 全流程的從業(yè)者。2. 消費(fèi)流水?dāng)?shù)據(jù)結(jié)構(gòu)與清洗拿到一份校園卡數(shù)據(jù)先做什么2.1 字段設(shè)計(jì)與數(shù)據(jù)字典先搞清楚每一列在說(shuō)什么校園消費(fèi)流水在不同學(xué)校的導(dǎo)出格式略有差異但核心字段基本一致。一份典型的流水表通常包含學(xué)號(hào)、消費(fèi)時(shí)間、消費(fèi)金額、商戶(hù)編號(hào)、商戶(hù)名稱(chēng)、消費(fèi)類(lèi)型、余額這幾列。學(xué)號(hào)是關(guān)聯(lián)學(xué)生基本信息的唯一鍵消費(fèi)時(shí)間精確到秒金額單位為元。消費(fèi)類(lèi)型字段常見(jiàn)取值包括“ POS 消費(fèi)”“補(bǔ)貼消費(fèi)”“退款”“圈存”其中退款和圈存不是真實(shí)消費(fèi)行為做行為分析前必須篩掉或單獨(dú)統(tǒng)計(jì)。拿到數(shù)據(jù)的第一件事不是寫(xiě)代碼而是逐字段確認(rèn)口徑。常見(jiàn)做法是寫(xiě)一段簡(jiǎn)單的 pandas 探查腳本輸出每列的非空數(shù)量、唯一值數(shù)量和樣例值對(duì)照數(shù)據(jù)字典核對(duì)。學(xué)號(hào)列如果混入教職工卡號(hào)或者消費(fèi)金額出現(xiàn)負(fù)數(shù)都會(huì)在后續(xù)分析中產(chǎn)生干擾。字符編碼也要注意從 Oracle 導(dǎo)出的數(shù)據(jù)常有 GBK 編碼問(wèn)題讀入時(shí)指定 encodingutf-8 或 encodinggbk 要提前試一遍否則中文商戶(hù)名會(huì)變成亂碼。import pandas as pd df pd.read_csv(campus_card_2023.csv, encodingutf-8, dtype{student_id: str}) print(df.shape) print(df.dtypes) for col in df.columns: print(col, df[col].nunique(), df[col].isnull().sum()) print(df[col].head(3).tolist())這段代碼的作用是快速摸清數(shù)據(jù)集的整體情況。dtype 參數(shù)把學(xué)號(hào)強(qiáng)制讀成字符串防止 Excel 里的科學(xué)計(jì)數(shù)法把學(xué)號(hào)變成浮點(diǎn)數(shù)nunique 統(tǒng)計(jì)唯一值數(shù)量用來(lái)判斷字段是不是主鍵isnull 統(tǒng)計(jì)空值數(shù)量字段缺失嚴(yán)重的列需要單獨(dú)處理。數(shù)據(jù)探查階段不要急著做任何轉(zhuǎn)換先把每一列的真實(shí)分布看清楚后面清洗才有依據(jù)。2.2 清洗規(guī)則與代碼金額異常、時(shí)間異常、重復(fù)消費(fèi)怎么處理清洗邏輯按優(yōu)先級(jí)排列順序不能亂。第一步剔除退款和圈存記錄只保留真實(shí)消費(fèi)第二步過(guò)濾金額異常比如金額小于 0.01 元或大于 200 元的單筆消費(fèi)前者通常是設(shè)備誤讀后者可能是批量采購(gòu)或代刷不屬于日常消費(fèi)第三步去重同一學(xué)號(hào)在同一秒同商戶(hù)金額完全相同的記錄視為重復(fù)流水第四步處理商戶(hù)名稱(chēng)中的空格和別名。# 僅保留真實(shí)消費(fèi) df df[df[trade_type] 消費(fèi)].copy() # 金額范圍過(guò)濾0.01 ~ 200 元 df df[(df[amount] 0.01) (df[amount] 200)].copy() # 去重同一學(xué)號(hào)、同一秒、同一商戶(hù)、同一金額 df df.drop_duplicates(subset[student_id, trade_time, merchant_id, amount]) # 商戶(hù)名稱(chēng)清洗去掉首尾空格替換全角空格 df[merchant_name] df[merchant_name].str.strip().str.replace(\u3000, ) df df.reset_index(dropTrue) print(df.shape)這個(gè)清洗漏斗是后續(xù)所有分析的基石。金額上限 200 元不是拍腦袋定的校園食堂和超市單筆消費(fèi)極少超過(guò)這個(gè)值超過(guò)的多半是代購(gòu)或集中采購(gòu)對(duì)個(gè)人經(jīng)濟(jì)評(píng)估會(huì)產(chǎn)生誤導(dǎo)。去重條件里的四個(gè)字段缺一不可只按學(xué)號(hào)和金額去重會(huì)誤刪同一食堂同菜價(jià)的正常記錄。清洗后建議按學(xué)號(hào)、時(shí)間排序?qū)С鲋虚g文件方便后面排查問(wèn)題時(shí)回查數(shù)據(jù)這一步也叫數(shù)據(jù)備份與恢復(fù)的準(zhǔn)備工作。2.3 數(shù)據(jù)質(zhì)量驗(yàn)證清洗前后對(duì)比與口徑核對(duì)清洗完成不代表數(shù)據(jù)能用還要做一輪質(zhì)量驗(yàn)證。對(duì)比清洗前后的總筆數(shù)、總金額、覆蓋學(xué)號(hào)數(shù)這些指標(biāo)能反映清洗邏輯是否過(guò)度或不足。比如全校三萬(wàn)學(xué)生清洗后只剩一萬(wàn)人有消費(fèi)記錄那說(shuō)明數(shù)據(jù)導(dǎo)出時(shí)可能漏了部分食堂或部分時(shí)間段需要重新拉取。更細(xì)的口徑核對(duì)方式是抽查某幾個(gè)學(xué)生把他們的逐筆流水打出來(lái)人工核對(duì)確認(rèn)金額和商戶(hù)名稱(chēng)字段沒(méi)有解析錯(cuò)位。before_count len(df_raw) after_count len(df) print(f清洗前 {before_count} 條清洗后 {after_count} 條刪除 {(before_count-after_count)/before_count:.1%}) valid_students df[student_id].nunique() print(f覆蓋學(xué)生數(shù) {valid_students})刪除比例超過(guò) 15% 時(shí)就要懷疑數(shù)據(jù)源本身有問(wèn)題。正常情況下退款和圈存記錄占比約 5%~8%金額異常和重復(fù)記錄占比很低總刪除比例超過(guò) 15% 大概率是導(dǎo)出時(shí)翻倍或主鍵設(shè)計(jì)有問(wèn)題。覆蓋學(xué)生數(shù)是另一個(gè)關(guān)鍵指標(biāo)如果少于全校人數(shù)的 80%說(shuō)明部分樓棟或校區(qū)的消費(fèi)機(jī)沒(méi)有納入采集范圍評(píng)估結(jié)論會(huì)有偏。3. 消費(fèi)行為特征提取從流水到每名學(xué)生一張畫(huà)像3.1 消費(fèi)水平特征日均消費(fèi)、月均消費(fèi)和消費(fèi)分位數(shù)行為分析的第一步是把逐筆流水匯總成學(xué)生維度特征。最常見(jiàn)的特征組是消費(fèi)水平類(lèi)總消費(fèi)金額、日均消費(fèi)、月均消費(fèi)、消費(fèi)天數(shù)、單筆平均金額、消費(fèi)金額中位數(shù)。日均消費(fèi)比總消費(fèi)更能反映真實(shí)水平因?yàn)榭偨痤~受在校天數(shù)影響兩個(gè)消費(fèi)水平相同的學(xué)生一個(gè)全年在校一個(gè)經(jīng)?;丶铱偨痤~會(huì)差很多。中位數(shù)比均值更穩(wěn)健不會(huì)被偶爾一次大額消費(fèi)拉偏。計(jì)算這些特征時(shí)要先按學(xué)號(hào)和時(shí)間戳排序再按月做匯總。月均消費(fèi)的計(jì)算要注意跨月問(wèn)題一筆 23:59 的記錄屬于哪個(gè)月取決于記賬時(shí)間統(tǒng)一按 trade_time 所在的自然月歸類(lèi)即可。消費(fèi)天數(shù)要按日期去重不能直接數(shù)流水條數(shù)否則一頓飯刷三次會(huì)被當(dāng)成三天。df[trade_date] pd.to_datetime(df[trade_time]).dt.date df[trade_month] pd.to_datetime(df[trade_time]).dt.month student_daily df.groupby([student_id, trade_date]).agg( daily_amount(amount, sum), daily_count(amount, count) ).reset_index() student_level student_daily.groupby(student_id).agg( total_amount(daily_amount, sum), active_days(daily_amount, count), avg_daily_amount(daily_amount, mean), median_daily_amount(daily_amount, median), max_daily_amount(daily_amount, max) ).reset_index()student_level 的每一行就是一名學(xué)生的消費(fèi)水平畫(huà)像。active_days 是實(shí)際消費(fèi)天數(shù)這個(gè)指標(biāo)能識(shí)別“幽靈學(xué)生”——學(xué)號(hào)在冊(cè)但幾乎不消費(fèi)可能是休學(xué)、交換或卡丟失。avg_daily_amount 和 median_daily_amount 的差值如果長(zhǎng)期偏大說(shuō)明該學(xué)生的消費(fèi)波動(dòng)劇烈可能有不規(guī)律的校外就餐習(xí)慣這類(lèi)學(xué)生的經(jīng)濟(jì)評(píng)估要結(jié)合其他特征綜合判斷不能只看均值。3.2 消費(fèi)結(jié)構(gòu)特征食堂、超市、水房與生活必需消費(fèi)占比消費(fèi)結(jié)構(gòu)比消費(fèi)水平更能說(shuō)明問(wèn)題。食堂消費(fèi)是生存型消費(fèi)超市消費(fèi)偏生活改善型水房和浴室消費(fèi)是剛需。把商戶(hù)名稱(chēng)歸類(lèi)成幾個(gè)功能大類(lèi)再計(jì)算每類(lèi)消費(fèi)金額占總金額的比例就能看出一個(gè)學(xué)生的錢(qián)主要花在哪里。消費(fèi)結(jié)構(gòu)特征在貧困生認(rèn)定中非常關(guān)鍵經(jīng)濟(jì)困難學(xué)生的食堂消費(fèi)占比通常偏高生活改善型消費(fèi)占比偏低。def categorize_merchant(name): if any(k in name for k in [一食堂, 二食堂, 三食堂, 風(fēng)味餐廳, 清真]): return canteen elif any(k in name for k in [超市, 小賣(mài)部, 便利店]): return market elif any(k in name for k in [開(kāi)水, 浴室, 洗衣]): return daily else: return other df[category] df[merchant_name].apply(categorize_merchant) category_pivot df.groupby([student_id, category])[amount].sum().unstack(fill_value0) for cat in [canteen, market, daily]: category_pivot[f{cat}_pct] category_pivot[cat] / category_pivot.sum(axis1)商戶(hù)歸類(lèi)規(guī)則的先后順序有講究把“風(fēng)味餐廳”放在超市前面因?yàn)樯虘?hù)名稱(chēng)可能同時(shí)包含“超市”和“餐廳”字樣。category_pivot 最終要 merge 回 student_level形成完整的特征寬表。canteen_pct 的特征分布通常呈現(xiàn)兩頭尖中間平的形態(tài)大部分學(xué)生在 50%~80% 之間低于 30% 的學(xué)生大概率經(jīng)常在校外就餐高于 90% 的學(xué)生則高度依賴(lài)校內(nèi)食堂這兩類(lèi)人群需要分別關(guān)注。4. 學(xué)生經(jīng)濟(jì)評(píng)估模型閾值打分還是聚類(lèi)分檔4.1 經(jīng)濟(jì)評(píng)估指標(biāo)體系與標(biāo)簽設(shè)計(jì)經(jīng)濟(jì)評(píng)估不能直接拿消費(fèi)金額給學(xué)生貼“貧困”標(biāo)簽因?yàn)橄M(fèi)水平和家庭經(jīng)濟(jì)狀況之間隔著個(gè)人消費(fèi)習(xí)慣這層緩沖。合理的做法是構(gòu)造一個(gè)綜合指標(biāo)把消費(fèi)水平、消費(fèi)結(jié)構(gòu)、消費(fèi)規(guī)律性和穩(wěn)定性組合起來(lái)。指標(biāo)體系常見(jiàn)三層第一層是消費(fèi)能力分由日均消費(fèi)、月均消費(fèi)和單筆均值構(gòu)成第二層是消費(fèi)質(zhì)量分由食堂占比、超市占比和必需消費(fèi)占比構(gòu)成第三層是消費(fèi)穩(wěn)定性分由消費(fèi)天數(shù)的月間變異系數(shù)衡量。標(biāo)簽設(shè)計(jì)有兩種路線(xiàn)。第一種是閾值打分法給每個(gè)指標(biāo)設(shè)分段閾值累加得到經(jīng)濟(jì)壓力指數(shù)分?jǐn)?shù)越高代表經(jīng)濟(jì)壓力越大第二種是聚類(lèi)分檔法用無(wú)監(jiān)督聚類(lèi)把學(xué)生分成若干檔再結(jié)合已知的資助名單校驗(yàn)檔位的合理性。兩種方法各有利弊閾值打分可解釋性強(qiáng)但閾值設(shè)定有主觀性聚類(lèi)分檔客觀但聚類(lèi)結(jié)果需要人工命名檔位。我一般先做聚類(lèi)看分布形態(tài)再用閾值法校準(zhǔn)檔位邊界。4.2 聚類(lèi)分檔實(shí)現(xiàn)特征標(biāo)準(zhǔn)化與 KMeans 參數(shù)選擇聚類(lèi)前必須做標(biāo)準(zhǔn)化否則金額特征的數(shù)值范圍會(huì)碾壓比例特征聚類(lèi)結(jié)果基本等于只按消費(fèi)金額分組。標(biāo)準(zhǔn)化用 StandardScaler 即可不需要做更復(fù)雜的歸一化。KMeans 的 K 值可以用輪廓系數(shù)選但校園消費(fèi)數(shù)據(jù)的類(lèi)別邊界本身模糊經(jīng)驗(yàn)上 K3 或 K4 效果較好K3 對(duì)應(yīng)“消費(fèi)水平較高、中等、較低”三檔K4 多出來(lái)的一檔往往是“消費(fèi)水平高但食堂占比異常高”的特殊人群。from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans feature_cols [avg_daily_amount, median_daily_amount, active_days, canteen_pct, market_pct, daily_pct] X student_profile[feature_cols].fillna(0) X_scaled StandardScaler().fit_transform(X) kmeans KMeans(n_clusters4, random_state42, n_init10) student_profile[economic_cluster] kmeans.fit_predict(X_scaled) cluster_summary student_profile.groupby(economic_cluster)[feature_cols].mean() print(cluster_summary.round(2))n_init10 是 KMeans 在 sklearn 1.2 之后的默認(rèn)值作用是用多個(gè)隨機(jī)質(zhì)心初始化跑多次取最優(yōu)避免局部最優(yōu)。fillna(0) 處理的是那些整月沒(méi)有任何消費(fèi)記錄的學(xué)生他們的占比特征為空補(bǔ)零表示不參與該維度計(jì)算。跑完聚類(lèi)后不要急著用先看每個(gè)簇的特征均值是否和人工經(jīng)驗(yàn)一致如果聚類(lèi)結(jié)果出現(xiàn)“高消費(fèi)高食堂占比”這種反直覺(jué)組合說(shuō)明標(biāo)準(zhǔn)化前的特征里有強(qiáng)相關(guān)性需要考慮刪除冗余特征或改用 PCA 降維后再聚類(lèi)。4.3 模型結(jié)果校驗(yàn)與資助名單的交叉驗(yàn)證聚類(lèi)分檔完成后必須做一輪外部校驗(yàn)。最常見(jiàn)的做法是把聚類(lèi)結(jié)果與學(xué)校已有的貧困生資助名單做交叉比對(duì)計(jì)算高經(jīng)濟(jì)壓力檔位中學(xué)生被認(rèn)定為困難生的比例。這個(gè)比例不需要很高因?yàn)橘Y助認(rèn)定還包含家庭突發(fā)變故等消費(fèi)數(shù)據(jù)看不到的因素但比例如果低于 10%說(shuō)明特征設(shè)置或聚類(lèi) K 值有問(wèn)題需要回溯調(diào)整。aid_df pd.read_csv(aid_list.csv, dtype{student_id: str}) merged student_profile.merge(aid_df, onstudent_id, howleft) merged[is_aided] merged[aid_level].notnull().astype(int) cross merged.groupby(economic_cluster)[is_aided].agg([mean, count]) cross.columns [aid_ratio, student_count] print(cross.round(3))aid_ratio 就是每個(gè)簇中獲得資助的學(xué)生占比。經(jīng)濟(jì)壓力最高的簇這個(gè)比例一般應(yīng)在 25%~40% 之間比例太低說(shuō)明聚類(lèi)沒(méi)抓住貧困特征比例超過(guò) 50% 反而要懷疑特征里混入了資助結(jié)果相關(guān)的泄漏變量比如直接用了補(bǔ)貼金額做特征。5. 校園消費(fèi)分析的常見(jiàn)問(wèn)題與避坑數(shù)據(jù)質(zhì)量、隱私邊界與模型翻車(chē)點(diǎn)5.1 現(xiàn)象清洗后覆蓋學(xué)生數(shù)驟減遇到過(guò)項(xiàng)目跑完清洗流程原本三萬(wàn)學(xué)生的數(shù)據(jù)集只剩一萬(wàn)八千人有消費(fèi)記錄。逐層排查發(fā)現(xiàn)退款和圈存記錄的 trade_type 字段取值不統(tǒng)一有的叫“退款”有的叫“退費(fèi)”還有的用數(shù)字編碼“3”表示。原因是不同校區(qū)的消費(fèi)機(jī)系統(tǒng)版本不一致導(dǎo)出的字典表沒(méi)同步。解決方式是在清洗前先打印所有 trade_type 的唯一值列表人工確認(rèn)全部取值后寫(xiě)成過(guò)濾白名單不要用黑名單過(guò)濾。5.2 現(xiàn)象聚類(lèi)結(jié)果出現(xiàn)“高消費(fèi)高食堂占比”簇K4 的聚類(lèi)結(jié)果里出現(xiàn)一個(gè)日均消費(fèi)很高但食堂消費(fèi)占比也接近 90% 的簇初看違反直覺(jué)。查數(shù)據(jù)發(fā)現(xiàn)這些學(xué)生的消費(fèi)記錄集中在風(fēng)味餐廳和清真食堂這些商戶(hù)的人均消費(fèi)顯著高于普通食堂。解決方式是在商戶(hù)歸類(lèi)時(shí)把風(fēng)味餐廳單獨(dú)拆成一個(gè)類(lèi)別而不是和普通食堂合并。這個(gè)坑的本質(zhì)是商戶(hù)分類(lèi)粒度太粗把均價(jià)差異大的商戶(hù)混在一起特征信息量被稀釋了。5.3 現(xiàn)象部分學(xué)生消費(fèi)天數(shù)極少導(dǎo)致評(píng)估失真有些學(xué)生一個(gè)月只在食堂消費(fèi)三到五天日均消費(fèi)算出來(lái)異常高被聚類(lèi)分到高消費(fèi)檔。人工回查發(fā)現(xiàn)這部分學(xué)生是校外實(shí)習(xí)或走讀生只偶爾回校吃飯。解決方式是在特征矩陣中增加 active_days 的過(guò)濾邏輯消費(fèi)天數(shù)少于當(dāng)月天數(shù) 30% 的學(xué)生不參與聚類(lèi)單獨(dú)標(biāo)記為 low_activity 人群由輔導(dǎo)員線(xiàn)下核實(shí)。這個(gè)處理在分析報(bào)告里必須寫(xiě)明否則評(píng)估結(jié)論會(huì)被質(zhì)疑。5.4 現(xiàn)象跨學(xué)期數(shù)據(jù)拼接后消費(fèi)水平整體抬升項(xiàng)目數(shù)據(jù)集如果橫跨兩個(gè)學(xué)期直接按全年匯總算日均消費(fèi)會(huì)發(fā)現(xiàn)高消費(fèi)檔人數(shù)多了不少。原因是春季學(xué)期有開(kāi)學(xué)季和節(jié)日消費(fèi)高峰秋季學(xué)期有迎新季不同學(xué)期的消費(fèi)物價(jià)也有調(diào)整。解決方式是引入學(xué)期字段按月計(jì)算特征時(shí)加入學(xué)期虛擬變量或者干脆只分析一個(gè)完整學(xué)期的數(shù)據(jù)保證口徑一致。多學(xué)期分析要按月生成特征后做時(shí)序?qū)Ρ炔荒苤苯悠戳魉?.5 現(xiàn)象評(píng)估模型跑完無(wú)法落地聚類(lèi)報(bào)告做得再漂亮如果學(xué)校輔導(dǎo)員看不懂模型結(jié)論就進(jìn)不了資助認(rèn)定流程。踩過(guò)的坑是只輸出簇編號(hào)和特征均值沒(méi)有給每個(gè)學(xué)生一句自然語(yǔ)言描述。解決方式是生成評(píng)估結(jié)果時(shí)附帶規(guī)則化的文字說(shuō)明比如“該生日均消費(fèi)低于全校 25% 分位食堂消費(fèi)占比高于 80%建議關(guān)注”并且提供按學(xué)院、按年級(jí)的匯總交叉表。模型結(jié)果的價(jià)值在決策鏈路里不在模型本身。6. 把評(píng)估結(jié)果用起來(lái)消費(fèi)畫(huà)像可視化與按月更新的評(píng)估流程聚類(lèi)分檔只是項(xiàng)目的中途站真正的終點(diǎn)是把結(jié)果嵌入學(xué)校的學(xué)生工作流程。每月初從一卡通系統(tǒng)增量導(dǎo)出上月流水跑一遍清洗和特征提取更新每名學(xué)生的經(jīng)濟(jì)評(píng)估檔案再把結(jié)果推送給學(xué)生工作管理系統(tǒng)。這個(gè)過(guò)程要寫(xiě)成定時(shí)腳本不能靠人工每月手動(dòng)跑一次否則維護(hù)成本會(huì)拖垮項(xiàng)目。import datetime today datetime.date.today() first_day today.replace(day1) last_month_end first_day - datetime.timedelta(days1) last_month_start last_month_end.replace(day1) monthly_raw load_monthly_data(last_month_start, last_month_end) monthly_clean clean_flow(monthly_raw) monthly_features build_student_features(monthly_clean) monthly_profile update_profile(monthly_features, last_month_end)這段代碼展示的是月度更新流程的框架三個(gè)函數(shù)分別對(duì)應(yīng)清洗、特征提取和畫(huà)像更新。load_monthly_data 從數(shù)據(jù)倉(cāng)庫(kù)按時(shí)間范圍取數(shù)clean_flow 復(fù)用第 2 章的清洗邏輯build_student_features 復(fù)用第 3 章的特征工程update_profile 把新月份的特征合并進(jìn)歷史畫(huà)像并重算分檔。關(guān)鍵點(diǎn)是特征的口徑要和上月嚴(yán)格一致任何規(guī)則改動(dòng)都要先對(duì)歷史數(shù)據(jù)回放否則累計(jì)畫(huà)像會(huì)出現(xiàn)突變??梢暬窗迨亲屧u(píng)估結(jié)果被非技術(shù)用戶(hù)接受的最有效手段。用 echarts 數(shù)據(jù)可視化做一個(gè)簡(jiǎn)單的月度趨勢(shì)頁(yè)面左側(cè)是全校消費(fèi)水平分布直方圖右側(cè)是各學(xué)院的經(jīng)濟(jì)壓力分檔占比橫向柱狀圖下邊是重點(diǎn)關(guān)注學(xué)生列表。echarts 的配置項(xiàng)不復(fù)雜關(guān)鍵是數(shù)據(jù)接口要設(shè)計(jì)好前端只按學(xué)院、年級(jí)、月份三個(gè)維度篩選取數(shù)。接口返回的 JSON 結(jié)構(gòu)建議預(yù)先聚合好不要讓前端做二次統(tǒng)計(jì)否則大數(shù)據(jù)量下頁(yè)面會(huì)卡頓。最后說(shuō)一個(gè)習(xí)慣項(xiàng)目交付時(shí)除了代碼和運(yùn)行文檔一定要附一份數(shù)據(jù)字典和清洗規(guī)則的變更記錄表。哪個(gè)月改了金額過(guò)濾閾值哪個(gè)月新增了商戶(hù)分類(lèi)逐條記下來(lái)。這個(gè)項(xiàng)目的坑幾乎都出在數(shù)據(jù)口徑上沒(méi)有變更記錄三個(gè)月后再跑一次全量分析你會(huì)發(fā)現(xiàn)自己都看不懂自己之前定的規(guī)則。做這個(gè)方向最深的體會(huì)是校園消費(fèi)行為分析的技術(shù)門(mén)檻不高難點(diǎn)在于對(duì)數(shù)據(jù)口徑的死磕和對(duì)業(yè)務(wù)邊界的拿捏。經(jīng)濟(jì)評(píng)估結(jié)果能幫輔導(dǎo)員發(fā)現(xiàn)那些不會(huì)主動(dòng)開(kāi)口的困難學(xué)生但也可能因?yàn)閿?shù)據(jù)缺失誤傷自尊心。所以我在每次生成重點(diǎn)關(guān)注名單時(shí)都會(huì)在報(bào)告首頁(yè)加一行提醒消費(fèi)數(shù)據(jù)只能作為參考線(xiàn)索最終認(rèn)定必須結(jié)合線(xiàn)下談話(huà)。這份克制和學(xué)生工作者的經(jīng)驗(yàn)判斷一樣重要希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取