據(jù)分析與可視化Python課設(shè):從數(shù)據(jù)清洗到閉環(huán)報告)
簡介一份面向計算機(jī)、電子信息工程、數(shù)學(xué)等專業(yè)大學(xué)生的新冠肺炎疫情數(shù)據(jù)分析與可視化完整課設(shè)項目可用于課程設(shè)計、期末大作業(yè)或畢業(yè)設(shè)計參考適合需要從零搭建數(shù)據(jù)采集、清洗、分析與可視化流程的讀者。項目包共57個文件包含17個Python腳本涉及微博輿情爬蟲、疫情數(shù)據(jù)爬取、分詞、邏輯回歸預(yù)測、地圖與詞云可視化2個Jupyter Notebook疫情分析與預(yù)測、NLP處理以及5個CSV疫情數(shù)據(jù)集、5個HTML交互頁面、算法設(shè)計Word報告和多張結(jié)果圖片整體約3.94MB。已有424人學(xué)習(xí)下載。借助這份高分作品讀者可以快速掌握新冠時序預(yù)測與情感分析的具體實現(xiàn)理解數(shù)據(jù)爬取、預(yù)處理、模型構(gòu)建、可視化展示的完整鏈路并直接復(fù)用其中代碼和圖表生成方案有效節(jié)省課設(shè)開發(fā)與報告撰寫時間。1. 從 zip 解壓到跑通只算開始疫情課設(shè)要的是能說清的分析閉環(huán)很多人拿到“新冠肺炎疫情數(shù)據(jù)分析與可視化python完整課設(shè)和代碼報告.zip”之后第一件事是解壓、裝庫、運(yùn)行看到彈出折線圖就以為完事了。真正到答辯或驗收時老師盯著圖問一句“這個日新增是你算出來的還是文件里直接帶的”“地圖上的省份名和你數(shù)據(jù)里的省份對不對得上”很多人當(dāng)場垮掉。這門課設(shè)的核心不是“能跑出圖”而是“數(shù)據(jù)怎么來→清洗成什么結(jié)構(gòu)→圖上畫的是什么→結(jié)論怎么從圖里長出來”整條鏈路閉環(huán)。“新冠肺炎疫情數(shù)據(jù)分析與可視化python”這串詞說白了就是拿一份公開的疫情表格用 pandas 清洗用 pyecharts 畫趨勢、畫地圖再用一兩段指標(biāo)或模型把結(jié)論寫進(jìn)報告。適合剛學(xué)完 Python 基礎(chǔ)、要交課程設(shè)計或者想在簡歷里放一個“從數(shù)據(jù)到可視化到報告”完整作品的人。如果已經(jīng)有底子直接跳到第 5 章避坑清單也不虧。2. 數(shù)據(jù)獲取與清洗把疫情 csv 揉成一張能畫圖的長表公開疫情數(shù)據(jù)和你在教程里看到的小樣例最大的區(qū)別是“它有手有腳”要么寬表里橫著一排日期列要么長表動輒幾十萬行字段名也不是同一個風(fēng)格。做這個課設(shè)第一步不是畫圖而是定口徑。先搞清楚我們要什么一張“日期 國家 累計確診 累計死亡 累計康復(fù)”的干凈長表再加一個“日新增”列后面所有圖表都從這里出。2.1 先看清表格結(jié)構(gòu)寬表和長表是兩種世界拿到 zip 后先別急著寫畫圖代碼打開數(shù)據(jù)文件看前幾行。疫情公開數(shù)據(jù)常見兩種存儲格式寬表每行是一個國家或省份后面的列是連續(xù)的日期格子里的值是“截止該日期的累計確診”。這種表人類看著方便但 pandas 畫圖很難直接消費(fèi)。長表只有幾列一般包含 Province/State、Country/Region、Date、Confirmed、Deaths、Recovered。這種結(jié)構(gòu)對 pandas 最友好groupby、篩選、合并都不容易出錯。先做這一步import pandas as pd raw pd.read_csv(data/covid_global.csv, nrows5) print(raw.columns.tolist()) print(raw.head())nrows5 只讀前 5 行目的是快速確認(rèn)列名、日期格式和分隔符。如果你拿到的文件是 xlsx 或 xls把 pd.read_csv 換成 pd.read_excel 即可兩者后續(xù)處理一致。這一步花不了一分鐘但能避免后面幾十次報錯。寬表和長表沒有誰好誰壞但處理路徑完全不同。寬表適合用 melt 壓縮成行長表適合直接 rename 和 groupby。先判斷自己手里是哪種再決定走哪個清洗分支比強(qiáng)行套網(wǎng)上的教程代碼靠譜得多。見過不少翻車現(xiàn)場手里是寬表硬套長表的代碼跑出來的圖全是一條水平線因為 pandas 把整列日期當(dāng)成了一個單獨(dú)字段。2.2 用 pandas 三行命令把寬表變成可計算的長表寬表轉(zhuǎn)長表是疫情課設(shè)里最高頻的操作。以一份全球累計確診寬表為例結(jié)構(gòu)大概是Country/Region 作為第一列后面跟著 1/22/20、1/23/20…… 這種日期列。轉(zhuǎn)換代碼如下long_df raw.melt( id_vars[Province/State, Country/Region, Lat, Long], var_namedate, value_nameconfirmed, ) long_df[date] pd.to_datetime(long_df[date], format%m/%d/%y) long_df ( long_df.groupby([Country/Region, date], as_indexFalse)[confirmed] .sum() .sort_values([Country/Region, date]) ) long_df[daily_new] ( long_df.groupby(Country/Region)[confirmed] .diff() .fillna(0) .clip(lower0) )這段代碼的邏輯分四步melt 把幾十個日期列壓縮成 date 和 confirmed 兩列pd.to_datetime 指定 format 把美國式日期轉(zhuǎn)成 pandas 的 datetime 類型groupby 按“國家 日期”聚合解決同一個國家下分省份、分州導(dǎo)致多行的問題最后用 diff 算相鄰日期的差值得到每日新增。參數(shù)說明format 里的 %m/%d/%y 必須和文件里的日期格式一致如果文件里是 2020-01-22就要改成 format%Y-%m-%d。groupby 里的 sum() 把同一國家不同省份當(dāng)日數(shù)據(jù)合并如果某國數(shù)據(jù)是長表且已經(jīng)只有國家維度這步也不會出錯因為一個“國家日期”只有一行。clip(lower0) 是為了去掉 diff 算出來的負(fù)值——后文避坑章會細(xì)說。2.3 清洗的隱藏問題重復(fù)行、負(fù)值、日期格式寬表轉(zhuǎn)成長表只是第一步。真正讓課設(shè)翻車的往往是下面這些看起來不起眼的小問題。重復(fù)行非常常見多個數(shù)據(jù)源拼接時同一國家同一日期可能出現(xiàn)兩次。如果不去重日新增會被翻倍。去重代碼在聚合前后都要執(zhí)行一次long_df long_df.drop_duplicates( subset[Country/Region, date], keeplast )keeplast 表示后面出現(xiàn)的覆蓋前面出現(xiàn)的適合“后更新的數(shù)據(jù)更準(zhǔn)”的場景。注意 subset 不包含 confirmed因為我們要的是“國家日期”維度上去重。日期格式統(tǒng)一要在畫圖之前完成。如果不轉(zhuǎn) datetime直接畫圖時橫軸會被當(dāng)成字符串順序會是 2020-01-01、2020-02-01…… 這種詞典序節(jié)假日和換月的地方排序亂掉。轉(zhuǎn)成 datetime 后matplotlib 和 pyecharts 都能自動處理時間軸。還有一個容易忽略的點(diǎn)file 編碼。pandas 默認(rèn)按 utf-8 讀但很多公開 csv 是 ANSI 編碼。讀取時可以顯式指定long_df pd.read_csv(data/covid_global.csv, encodingutf-8)如果報 UnicodeDecodeError改成 encodinggbk 或 encodinglatin1 逐個試。清洗完導(dǎo)出時我會用 utf-8-sig 而不是 utf-8因為 utf-8-sig 會在文件開頭寫入 BOMExcel 打開中文不會亂碼long_df.to_csv(data/covid_clean.csv, indexFalse, encodingutf-8-sig)indexFalse 是為了不把 pandas 的行號寫進(jìn)文件utf-8-sig 是課設(shè)報告里 Word 引用表格的后悔藥。提示清洗階段保存一份 covid_clean.csv之后所有畫圖和建模都從這里讀不要再碰原始文件。這樣一旦分析出錯能很快區(qū)分是數(shù)據(jù)問題還是代碼問題而不是每次從頭跑。3. 可視化用 pyecharts 做報告能直接引用的趨勢圖和地圖數(shù)據(jù)清洗完接下來進(jìn)入視覺部分。選對可視化庫課設(shè)的觀感能直接提升一個檔次。3.1 為什么是 pyecharts 而不是 matplotlibmatplotlib 適合論文里那種嚴(yán)謹(jǐn)?shù)男〕叽鐖D但如果要做課設(shè)答辯或可視化大屏展示pyecharts 更合適pyecharts 本質(zhì)是把 echarts 數(shù)據(jù)可視化 的能力搬進(jìn)了 python輸出是一個自包含的 html 文件鼠標(biāo)懸停有提示框圖可以縮放、拖拽不需要前端功底就能拿到交互效果。報告里截圖用靜態(tài)圖答辯現(xiàn)場打開 html 給老師看交互兩種場景都覆蓋。另一個關(guān)鍵理由是地圖。pyecharts 的 Map 組件對國內(nèi)省份的中國地圖和全球國家地圖都有現(xiàn)成支持不需要自己找 GeoJSON、算投影。一套代碼下來趨勢圖、Top10 柱狀圖、省份地圖、時間線動畫全是同一個庫的語法學(xué)習(xí)成本低很多。3.2 折線圖和柱狀圖把趨勢與 Top10 寫進(jìn)報告報告里最保險、最不跳戲的三張圖全國或全球累計確診折線圖、每日新增折線圖、累計確診 Top10 國家柱狀圖。折線圖代碼from pyecharts.charts import Line from pyecharts import options as opts line Line(init_optsopts.InitOpts(width960px, height540px)) line.add_xaxis(date_labels) line.add_yaxis( 日新增確診, daily_values, is_smoothTrue, label_optsopts.LabelOpts(is_showFalse), linestyle_optsopts.LineStyleOpts(width3, color#d14a1e), ) line.set_global_opts( title_optsopts.TitleOpts(title日新增確診趨勢), tooltip_optsopts.TooltipOpts(triggeraxis, axis_pointer_typecross), datazoom_opts[opts.DataZoomOpts(range_start30, range_end100)], ) line.render(charts/line_daily.html)add_yaxis 里的 is_smoothTrue 讓折線平滑避免折線像鋸齒一樣扎眼label_opts 的 is_showFalse 是不在每個數(shù)據(jù)點(diǎn)上標(biāo)數(shù)字否則幾百個點(diǎn)全堆在圖上沒法看。datazoom_opts 是 pyecharts 的亮點(diǎn)圖表下方會出現(xiàn)一個縮放條默認(rèn) range_start30 表示只顯示后 70% 的數(shù)據(jù)老師拖縮放條就能看任意時間段細(xì)節(jié)。width 和 height 設(shè)置畫布尺寸報告里引用截圖時分辨率能撐得住。柱狀圖更簡單但有個參數(shù)必須調(diào)from pyecharts.charts import Bar bar Bar() bar.add_xaxis(top10_countries) bar.add_yaxis(累計確診, top10_values) bar.set_global_opts( title_optsopts.TitleOpts(title累計確診 Top10 國家), xaxis_optsopts.AxisOpts( axislabel_optsopts.LabelOpts(rotate-15) ), ) bar.render(charts/bar_top10.html)rotate-15 是 x 軸標(biāo)簽旋轉(zhuǎn) 15 度。國名通常較長不旋轉(zhuǎn)會疊在一起報告里截出來的圖全是黑坨坨。Top10 的選取很簡單按確診總數(shù)排序取前 10 個國家名和數(shù)值先算好再喂給柱狀圖不要在 add_xaxis 里臨時篩選。3.3 中國地圖和時間線做出可視化大屏的觀感國內(nèi)省份熱力地圖是疫情課設(shè)的保留節(jié)目。代碼并不長from pyecharts.charts import Map map_chart Map() map_chart.add( 累計確診, [list(z) for z in zip(province_names, province_values)], china, ) map_chart.set_global_opts( title_optsopts.TitleOpts(title國內(nèi)各省累計確診熱力), visualmap_optsopts.VisualMapOpts( min_0, max_int(province_values.max()), is_piecewiseTrue, pieces[ {min: 10000, color: #c12e2a}, {min: 1000, max: 9999, color: #fd8f42}, {min: 100, max: 999, color: #ffd45e}, {max: 99, color: #eaf6ee}, ], ), ) map_chart.render(charts/map_province.html)is_piecewiseTrue 配合 pieces 列表會把圖例分成幾個區(qū)間段而不是用一個連續(xù)色條。這樣設(shè)計的好處是低數(shù)值省份不會被高數(shù)值省份的顏色淹沒視覺效果更接近正式可視化大屏。pieces 里的 min、max、color 按自己數(shù)據(jù)量級改如果最大確診是 5 萬就把第一檔的 min 改成 50000。如果想把地圖做成隨時間變化的動畫用 Timelinefrom pyecharts.charts import Timeline timeline Timeline() for d in sample_dates: piece build_map_for_date(d) timeline.add(piece, time_pointd) timeline.add_schema(play_interval800, is_auto_playTrue) timeline.render(charts/timeline.html)build_map_for_date 是“傳一個日期返回一個該日期的 Map 實例”的函數(shù)你可以把上面的 Map 代碼包進(jìn)這個函數(shù)換數(shù)據(jù)源即可。add_schema 的 play_interval800 是自動播放時每幀間隔 800 毫秒is_auto_playTrue 讓頁面打開后自動播放。答辯演示到這一頁時地圖上色塊隨時間燃燒擴(kuò)散比任何靜態(tài)圖都有說服力這也是“python數(shù)據(jù)分析與可視化實踐”里最能體現(xiàn)工作量的一塊。4. 數(shù)據(jù)分析與模型用指標(biāo)和 SIR 模型把結(jié)論寫進(jìn)課設(shè)報告可視化解決“數(shù)據(jù)長什么樣”分析解決“數(shù)據(jù)說明什么”。只畫圖不分析報告就沒有結(jié)論答辯時只能念圖例。這一章講三個能落地到課設(shè)報告的產(chǎn)出增長率指標(biāo)、粗糙 R0、SIR 模型曲線。4.1 從圖到結(jié)論環(huán)比增速與一個粗糙 R0累計確診從 1 萬漲到 2 萬和從 100 萬漲到 101 萬同樣都漲了 1 萬但傳播勢頭完全不同。所以要算環(huán)比增長率china clean_df[clean_df[country] China].copy() china china.sort_values(date) china[growth_rate] china[confirmed].pct_change().fillna(0) * 100 china[daily_new_7d] ( china[daily_new].rolling(7, min_periods1).mean() ) china[r0_approx] ( china[daily_new].rolling(7).mean() / china[confirmed].shift(1).rolling(7).mean() ).fillna(0)pct_change() 自動算相鄰日期的百分比變化乘以 100 變成百分比。growth_rate 在疫情早期很高后期趨近于 0報告里可以寫“增長率從早期的高位回落到低位說明傳播被逐步壓制”。r0_approx 是我習(xí)慣用的粗糙估計用 7 天平均日新增除以 7 天前的累計確診表示每 1 個已感染者在一周內(nèi)平均催生出的新感染人數(shù)。這個值不是流行病學(xué)嚴(yán)格意義上的 R0但課程設(shè)計報告里作為“疫情擴(kuò)散速度的近似觀察”完全夠用答辯時老師更關(guān)心你是否理解它為什么只是一個近似。4.2 SIR 模型補(bǔ)一條趨勢曲線odeint 參數(shù)與邊界SIR 模型是疫情課設(shè)的加分項。它把人群分成易感者 S、感染者 I、康復(fù)者 R 三組用兩個參數(shù) beta 和 gamma 描述傳播和康復(fù)速度。實現(xiàn)用 scipy 的 odeintimport numpy as np from scipy.integrate import odeint N 1400.0 beta, gamma 0.21, 0.07 I0, R0 1.0, 0.0 S0 N - I0 - R0 t np.linspace(0, 300, 300) def sir(state, t, beta, gamma): S, I, R state dSdt -beta * S * I / N dIdt beta * S * I / N - gamma * I dRdt gamma * I return dSdt, dIdt, dRdt result odeint(sir, [S0, I0, R0], t, args(beta, gamma)) S, I, R result.Tbeta 是“感染者每天有效接觸的人數(shù)”gamma 是“感染者每天康復(fù)的比例”。beta0.21、gamma0.07 時一個感染者平均傳染 3 個人、病程約 14 天模擬曲線會在大約第 60 天達(dá)到感染峰值。想調(diào)參數(shù)看效果beta 越大峰值越高越靠前gamma 越大康復(fù)越快峰值越低。這兩組參數(shù)在報告里必須寫明否則模型就是黑匣子。把模擬感染人數(shù)和真實日新增畫在同一張圖時注意量綱。模擬的 N 是 1400 萬抽象量級真實日新增是幾百到幾萬直接疊加是一條壓扁的線。常見的做法有兩種真實日新增除以一個縮放常數(shù)或者模擬值乘一個縮放系數(shù)。更嚴(yán)謹(jǐn)?shù)臅鰠?shù)擬合但對課程設(shè)計來說散點(diǎn)與曲線的形態(tài)對照已經(jīng)足夠表達(dá)“模型趨勢 vs 現(xiàn)實趨勢”的關(guān)系。我會在代碼里注明這里做的是演示性對照不是擬合結(jié)果。import matplotlib matplotlib.use(Agg) import matplotlib.pyplot as plt plt.figure(figsize(10, 6)) plt.plot(t, I, labelSIR 模擬感染人數(shù), color#d73027) plt.scatter(real_idx, real_daily / scale_factor, s8, label真實日新增(歸一化)) plt.xlabel(Time (days)) plt.ylabel(People) plt.legend() plt.savefig(charts/sir_compare.png, dpi200)dpi200 保證截圖放進(jìn) Word 里不糊。scale_factor 需要你根據(jù)真實數(shù)據(jù)的峰值手動調(diào)讓兩條線大致同高目的是看形態(tài)而不是精確數(shù)值。報告里一定要寫清楚“SIR 模型沒有考慮隔離政策、無癥狀感染、檢測能力變化曲線僅作趨勢示意”。這樣反而顯得你懂邊界。4.3 報告編排結(jié)論先行圖表作為證據(jù)“代碼報告.zip”里的報告比代碼難寫得多。一份能扛住答辯的報告結(jié)構(gòu)我建議按這個順序組織摘要數(shù)據(jù)源、時間范圍、清洗方式三句話說清分析對象和主要結(jié)論。數(shù)據(jù)說明字段表、保留哪些維度、如何處理缺失值寫出 daily_new 的計算口徑。圖表解讀每張圖配 1-2 句結(jié)論例如“7 月第二周起日新增開始下降結(jié)合移動平均確認(rèn)拐點(diǎn)”。模型與局限SIR 的參數(shù)設(shè)定、為什么不能直接用模擬值放在“局限”里說透。附錄代碼清單、依賴環(huán)境、運(yùn)行順序。報告里不要貼大段代碼把關(guān)鍵統(tǒng)計量和參數(shù)放正文或表格代碼放附錄。我見過不少課設(shè)報告把 200 行代碼直接復(fù)制進(jìn)正文老師一眼掃過去就會覺得是在湊頁數(shù)。結(jié)論先行的意思是每一節(jié)第一句話就回答“這張圖說明了什么”然后再展開細(xì)節(jié)。數(shù)據(jù)分析課設(shè)的答辯時間通常很短老師看摘要就能判斷你有沒有真正跑通而不是只改了別人的圖。5. 避坑疫情課設(shè)最常見的 5 個翻車現(xiàn)場與排查課程設(shè)計出問題的地方往往不在分析本身而在環(huán)境、版本、編碼這些“yìn”上。下面 5 條是疫情課設(shè)里重復(fù)率最高的坑每條都是“現(xiàn)象 → 原因 → 解決”的排查邏輯。5.1 圖表里全是方塊字中文字體與編碼問題現(xiàn)象pyecharts 生成的 html 里標(biāo)題和圖例全是方塊、問號或亂碼尤其是 Windows 系統(tǒng)。原因分兩層一是數(shù)據(jù)源里的中文在讀取/導(dǎo)出時用了錯誤編碼csv 文件里的中文變成亂碼畫圖自然亂二是 pyecharts 生成的 html 里字體棧沒聲明中文字體瀏覽器回退失敗。解決數(shù)據(jù)文件讀取時顯式指定 encoding導(dǎo)出用 encodingutf-8-sig。pyecharts 畫圖時在 TitleOpts 和 LabelOpts 里顯式設(shè)置 font_family例如 font_familyMicrosoft YaHei。如果圖表是英文數(shù)據(jù)標(biāo)題寫成中文依然可能亂碼原因就是第二種。5.2 pyecharts 版本一變老教程代碼整段不能跑現(xiàn)象網(wǎng)上抄的代碼報錯信息是 “ImportError: cannot import name ‘Map’ from ‘pyecharts’” 或 “Timeline” 導(dǎo)入失敗。原因pyecharts 1.x 和 2.x 的 API 差異很大老教程多是 0.5.x 版本Map 的導(dǎo)入路徑完全不同。解決鎖定版本一條命令統(tǒng)一環(huán)境pip install pyecharts2.0.9導(dǎo)入方式統(tǒng)一寫成from pyecharts.charts import Map, Timeline, Line, Bar from pyecharts import options as opts這樣能避開絕大多數(shù)舊教程坑。如果用的是 Python 3.11 以上建議再確認(rèn) pyecharts 依賴的 simplejson 版本缺什么裝什么。5.3 中國地圖整塊空白省份名與地圖資源兩個坑現(xiàn)象地圖渲染出來全空白或只有個別省份有顏色。原因有兩類。第一類是省份名稱不匹配pyecharts 中國地圖內(nèi)置使用“北京”“上海”“湖北”這種不帶“市”“省”后綴的名稱而數(shù)據(jù)里可能寫的是“湖北省”“北京市”匹配不上就畫不出來。第二類是地圖資源沒加載新版 pyecharts 本地地圖文件需要單獨(dú)機(jī)制離線環(huán)境下 CDN 加載不到 echarts 地圖腳本整圖空白。解決名稱不匹配就用“湖北省”.replace(省, ) 這類規(guī)則清洗或者維護(hù)一個手工映射表。地圖資源加載失敗的先檢查項目里是否有 map js 文件沒有的話手動把地圖 js 文件下載到本地并注冊再用 render 生成 html。這門課設(shè)的所有圖表都要能在拆了網(wǎng)的答辯教室跑起來這一點(diǎn)提前確認(rèn)。5.4 “日新增”出現(xiàn)負(fù)值diff 的副作用現(xiàn)象每日新增折線圖里突然出現(xiàn)一個向下的尖刺數(shù)值為負(fù)。原因diff() 算的是“今天的累計值減昨天的累計值”。某些數(shù)據(jù)源在某個日期修正了之前的統(tǒng)計口徑例如把之前多算的病例減回去今天的累計值反而比昨天小diff 就產(chǎn)生負(fù)值。解決在計算 daily_new 后立刻 clipchina[daily_new] china[daily_new].clip(lower0)同時報告里寫一句“負(fù)值來源于統(tǒng)計口徑修正已按 0 處理”。這樣數(shù)據(jù)說明部分反而成了加分項。5.5 報告里的圖表糊成一片渲染與截圖分辨率現(xiàn)象html 里圖表很清晰截圖放到 Word 后文字發(fā)虛折線邊緣鋸齒嚴(yán)重。原因普通截屏按屏幕分辨率輸出Word 顯示時進(jìn)行了縮放如果直接用 pyecharts 的 render 輸出 png默認(rèn)分辨率也不高。解決用 snapshot-selenium 組件渲染高分辨率 pngpip install snapshot-seleniumfrom pyecharts.render import make_snapshot from snapshot_selenium import snapshot make_snapshot(snapshot, charts/line_daily.html, charts/line_daily.png, pixel_ratio2)pixel_ratio2 表示按 2 倍分辨率輸出圖里文字在 Word 里放大也清晰。比手動截圖穩(wěn)定得多。注意這 5 個坑不是互相獨(dú)立的。地圖空白時先看省份名再查資源文件日新增負(fù)值修完以后再畫圖別帶著臟數(shù)據(jù)直接可視化。6. 進(jìn)階用留出段數(shù)據(jù)自我驗證再用 Streamlit 做成可交互看板6.1 先驗證再交付留出三個月做回頭確認(rèn)課程設(shè)計交出去之前給自己留一道“凸出測試”只用截止到某年某月的數(shù)據(jù)清洗并畫圖之后三個月的真實數(shù)據(jù)不參與任何計算當(dāng)作未來數(shù)據(jù)來驗證。做法很簡單數(shù)據(jù)讀進(jìn)來后先按日期切一刀把后三個月單獨(dú)放一個變量train clean_df[clean_df[date] 2021-10-01] test clean_df[clean_df[date] 2021-10-01]訓(xùn)練部分觀察到的趨勢拐點(diǎn)、增長率回落等結(jié)論用 test 部分的真實值去比對如果測試段的實際變化方向與基于 train 段得出的趨勢判斷一致說明分析邏輯是成立的如果明顯矛盾優(yōu)先檢查清洗是否有誤。這個過程不用寫到報告里但它能幫你避免“分析結(jié)論只是事后諸葛亮式地描述一張圖”的尷尬。6.2 十個 Streamlit pyecharts 代碼把靜態(tài)報告變成可交互看板課設(shè)驗收時如果評委可以自己選國家、拉時間范圍效果比翻 ppt 強(qiáng)很多。用 streamlit 把之前渲染 html 的代碼包一層就是一個小型可視化大屏import streamlit as st import pandas as pd from pyecharts.charts import Line from pyecharts import options as opts import streamlit.components.v1 as components st.title(疫情數(shù)據(jù)展示看板) df pd.read_csv(data/covid_clean.csv, parse_dates[date]) country st.selectbox(選擇國家或地區(qū), sorted(df[country].unique())) sub df[df[country] country].sort_values(date) line Line() line.add_xaxis(sub[date].dt.strftime(%Y-%m-%d).tolist()) line.add_yaxis(累計確診, sub[confirmed].tolist(), is_smoothTrue) line.set_global_opts( title_optsopts.TitleOpts(titlef{country} 累計確診趨勢), datazoom_opts[opts.DataZoomOpts()], ) components.html(line.render_embed(), height480, width980)selectbox 生成下拉框組件會監(jiān)聽用戶選擇并重新執(zhí)行腳本。render_embed 是 pyecharts 提供的方法把圖表 html 內(nèi)嵌到 streamlit 頁面里不需要額外生成文件。運(yùn)行方式是streamlit run app.py我第一次交這類課設(shè)時只畫了折線圖和地圖答辯老師一句話就問住了我“日新增這個數(shù)到底是你算的還是文件里給的”從那以后我養(yǎng)成了一個習(xí)慣任何數(shù)據(jù)項目先把口徑寫在最前面再把驗證過程留一手寧可圖少一張也要把邏輯說到位。希望這份筆記能讓你少走幾段彎路把疫情數(shù)據(jù)課設(shè)做成一個真正能講的完整作品。本文還有配套的精品資源點(diǎn)擊獲取