據(jù)分析實戰(zhàn):用Python洞察能耗規(guī)律)
簡介面向制造業(yè)用電量預測的 LSTM 項目資源聚焦電力消耗數(shù)據(jù)中典型的周期性、趨勢性特征并針對時間序列建模長期依賴問題給出解決方案資源覆蓋數(shù)據(jù)預處理、模型構(gòu)建、訓練評估與預測結(jié)果對比等完整流程適合時間序列分析初學者、制造業(yè)能源管理從業(yè)者以及正在開展電力負荷預測課題或競賽的學生使用。壓縮包共 106 個文件以 CSV 預測結(jié)果文件、Python 腳本和 JPG 可視化圖表為主體另有 XML 工程配置、運行日志、PyTorch 模型權(quán)重 pth 及記錄訓練損失變化的 Excel 表格總大小僅 4.57MB目錄結(jié)構(gòu)清晰便于按需查閱。資源提供了不同時間步長2/4/6與多種損失函數(shù)MSE、SmoothL1Loss下的用電量預測結(jié)果并通過訓練損失記錄幫助判斷模型收斂和過擬合情況讀者可通過主程序快速復現(xiàn)實驗直觀觀察各參數(shù)對預測精度的影響進而掌握 LSTM 在能耗數(shù)據(jù)分析中的調(diào)參方法。目前已有 1517 人學習下載是一份兼顧代碼、數(shù)據(jù)與訓練記錄面向?qū)嶋H問題且容易上手的輕量級參考。 去年夏天我收到電費賬單時愣了一下——比前一個月多出接近一倍可我明明沒添什么大功率電器。翻出歷史賬單逐月對比發(fā)現(xiàn)用電量像坐過山車一樣忽上忽下卻又說不出具體是哪兒在耗電。后來我把智能電表里的歷史數(shù)據(jù)導出來用 Python 做了一遍完整的清洗、分析和可視化才真正看清自己家里的用電規(guī)律。這個用電量數(shù)據(jù)分享項目本質(zhì)上是教你把手里的用電量數(shù)據(jù)變成能指導行動的結(jié)論哪些電器是耗電大頭、峰谷時段怎么分布、電費異常是哪里出了問題。我當時做完之后把分析圖表分享到業(yè)主群不少鄰居照著排查還真找到了自家待機功耗過高的問題。這篇博文會把整個項目的思路、數(shù)據(jù)獲取方式、處理代碼、可視化和常見坑都寫清楚適合手里有智能電表數(shù)據(jù)或想自己統(tǒng)計家庭能耗的朋友參考也適合剛接觸 pandas 時間序列分析的新手拿來練手。1. 為什么要做用電量數(shù)據(jù)分析1.1 一次電費異常引發(fā)的需求數(shù)據(jù)分析最忌諱的就是沒有明確目的。我這次做用電量分析起因非常樸素——想知道錢花在哪了。家庭用電不像打車、網(wǎng)購那樣每筆都有明細賬單它只有一個總數(shù)字家里電器又多洗衣機、熱水器、空調(diào)、冰箱各自貢獻了多少基本靠猜。把用電量數(shù)據(jù)從月度粒度細化到當天甚至每15分鐘一個點之后很多問題一眼就能看出答案。比如我分析后發(fā)現(xiàn)自己家的電費大頭是電熱水器它在凌晨保溫加熱的耗電量比我白天開6小時電腦還多。這個結(jié)論在月賬單上根本看不出來但把逐日數(shù)據(jù)按小時聚合后凌晨那個穩(wěn)定存在的小高峰直接暴露了真相。1.2 這個分析適合誰、能解決什么問題這套分析思路既適合家庭用戶也適合小區(qū)物業(yè)、小型商戶做能耗摸底。對于個人來說能解決三個具體問題找到電費異常波動的真實原因而不是靠感覺猜識別出峰谷用電時段配合分時電價調(diào)整用電習慣發(fā)現(xiàn)待機功耗和老化電器做到有的放矢地更換或斷電如果你是剛學數(shù)據(jù)分析的開發(fā)者這個項目更是極佳的練手素材。它的數(shù)據(jù)量不大一年也就365條到幾萬條不需要分布式計算一張 Excel 表或 SQLite 數(shù)據(jù)庫就夠用但完整覆蓋了數(shù)據(jù)清洗、重采樣、聚合、可視化這一套核心流程比看著教程敲示例代碼有感覺得多。2. 數(shù)據(jù)從哪來三類典型來源2.1 智能電表的線上查詢現(xiàn)在很多地區(qū)的智能電表已經(jīng)支持高頻采集用電數(shù)據(jù)會定時上傳到供電企業(yè)的后臺。普通用戶最常見的獲取途徑是官方App或小程序一般能查到最近一年到兩年的每日用電量部分區(qū)域甚至支持查詢每15分鐘一個點的負荷曲線。我用的就是這類渠道導出的 CSV 文件字段通常包含時間、正向有功電量等需要自己在導出時留意時間粒度和單位kWh 還是 Wh。如果你所在區(qū)域的線上渠道查不到日數(shù)據(jù)還有個笨辦法每天固定時間抄一次電表讀數(shù)記錄到表格里。雖然麻煩但攢上兩三個月也能看出規(guī)律。參與過家庭能源管理系統(tǒng)項目的朋友還可以考慮加裝支持 Modbus 或 Wi-Fi 的智能電表模塊把數(shù)據(jù)自動采集到本機數(shù)據(jù)庫這樣連手動導出都省了。2.2 智能插座與獨立電表實測遇到單個電器耗電多少這種問題時總表數(shù)據(jù)幫不上忙需要用智能插座做支路測量。我買了一臺帶功率統(tǒng)計的 Wi-Fi 插座接在電熱水器前面用廠商 App 導出它一周的逐小時功率曲線。這個數(shù)據(jù)的好處是干凈、和具體設備強綁定缺點是覆蓋面小不適合做全家用電的整體分析。所以我的做法是總表數(shù)據(jù)負責看全貌插座數(shù)據(jù)負責定位具體設備兩者配合使用。2.3 公共數(shù)據(jù)集與工具準備如果你手上沒有自己的數(shù)據(jù)想直接練手可以用一些學術用途的公開數(shù)據(jù)集比如某些機構(gòu)發(fā)布的住宅用電數(shù)據(jù)這些數(shù)據(jù)通常是 CSV 格式時間跨度為一年以上字段比家庭導出的更規(guī)范包括時間戳、總用電量、分項用電量等。不過要注意這類數(shù)據(jù)集大多以教學和科研為目的分享時需注明出處。工具方面我的推薦比較固定Python pandas 做數(shù)據(jù)處理matplotlib 做靜態(tài)圖pyecharts 或 Plotly 做交互式圖表。項目做大了想長期保存數(shù)據(jù)的話可以加一個 SQLite幾百兆以內(nèi)的用電記錄它都能輕松應對。開發(fā)環(huán)境裝 Anaconda 或直接pip install pandas matplotlib pyecharts都行不復雜。3. 數(shù)據(jù)預處理拿到手先別急著畫圖3.1 時間字段的清洗大部分人拿到電表導出的數(shù)據(jù)第一件事就是直接plt.plot結(jié)果畫出來往往是一團亂麻。原因多半出在時間字段上時間列是字符串、時區(qū)不對、采樣間隔不均勻、有重復時間戳。我處理原始 CSV 的第一步永遠是統(tǒng)一時間格式import pandas as pd df pd.read_csv(elec_raw.csv, encodingutf-8-sig) df[time] pd.to_datetime(df[time], format%Y-%m-%d %H:%M:%S) df df.set_index(time).sort_index() print(df.head())需要注意編碼問題。供電企業(yè)導出的 CSV 在 Windows 下經(jīng)常是 GBK 編碼直接用 pandas 讀取會報錯我一般先試utf-8-sig不行就換gbk。時間格式也要以實際為準有的是2023/07/01 08:15有的是2023-07-01 08:15:00最好顯式指定format否則 pandas 自動推斷在幾萬條數(shù)據(jù)上會慢得讓人懷疑人生。3.2 缺失值與異常值處理真實用電數(shù)據(jù)幾乎沒有完全干凈的。通信故障、電表重啟、偶爾上傳失敗都會造成數(shù)據(jù)缺失或異常。我最常遇到的異常值有兩種用電量出現(xiàn)負值以及單點數(shù)值突然跳到平時的幾十倍。負值一般是電表重啟或現(xiàn)場校準造成的處理方式是直接剔除# 剔除負值和超過99.9%分位數(shù)的離譜值 df df[df[value] 0] upper_limit df[value].quantile(0.999) df df[df[value] upper_limit]缺失值要不要補、怎么補取決于分析目的。如果是畫年趨勢圖少量缺失點完全不影響直接跳過即可。如果是做日用電量匯總比如把15分鐘數(shù)據(jù)重采樣成每日總量可以先用前向填充把短時間缺口補上再聚合。我個人的經(jīng)驗是超過3個小時的連續(xù)缺失就不要再強行插值了寧可讓它空著也不要制造出看似平滑實則虛構(gòu)的曲線。這個項目里我試過用線性插值補一個長達兩天的缺口結(jié)果畫出來的曲線在缺口段出現(xiàn)明顯的凹陷極易誤導判斷。3.3 數(shù)據(jù)入庫與統(tǒng)一單位清洗完的數(shù)據(jù)我會存一份副本格式統(tǒng)一為 Parquet 或 SQLite字段統(tǒng)一為time、value、unit。單位統(tǒng)一很關鍵有的電表導出的是 kWh有的是 Wh如果混著計算差了1000倍后面的分析全白做。我的做法是在讀入時強制轉(zhuǎn)成 kWhdf[value] df[value] / 1000.0 # 如果原始單位是Wh df df.rename(columns{value: kwh})另外建議建一張meta表記錄數(shù)據(jù)來源、時間跨度、單位、異常處理說明。這個小習慣在數(shù)據(jù)量變大、來源變多之后特別有用不然過上兩個月回頭再看很容易忘記某列到底代表什么。4. 核心分析把用電規(guī)律挖出來4.1 整體趨勢與周期規(guī)律分析的第一步是看整體趨勢。把清洗好的數(shù)據(jù)按天重采樣得到逐日用電量曲線daily df[kwh].resample(D).sum() daily.plot(figsize(12, 4))從這條曲線上能直觀看到季節(jié)變化、周末和工作日的差異以及某個時間段的異常抬升。以我的數(shù)據(jù)為例6月到8月的日均用電量明顯高出春秋季一倍多這個結(jié)論符合直覺但真正讓我意外的是1月的數(shù)據(jù)——因為冬天開電暖器用電量竟然和7月開空調(diào)時相差無幾。有了整體曲線后進一步疊加星期維度看周期性。方法很簡單把數(shù)據(jù)按星期幾分組求平均日用電量daily_avg_by_weekday daily.groupby(daily.index.dayofweek).mean() daily_avg_by_weekday.index [周一, 周二, 周三, 周四, 周五, 周六, 周日] print(daily_avg_by_weekday)我實測下來工作日的用電形態(tài)差異不大但周六會出現(xiàn)一個明顯的高峰原因是周末在家時間長、做飯次數(shù)多熱水器和抽油煙機使用頻率上升。而且周日用電量比周六略微回落估計是不少家庭周日選擇外出。4.2 峰谷時段拆解比周幾用電多更實用的是一天之內(nèi)的高峰時段分布。配合峰谷分時電價能直接幫你省錢。如果電表數(shù)據(jù)是15分鐘或1小時一個點就可以按小時做聚合看一天24小時的負荷曲線hourly df[kwh].resample(H).sum() hourly_avg_by_hour hourly.groupby(hourly.index.hour).mean() # 找出最高和最低的三個時段 print(hourly_avg_by_hour.sort_values(ascendingFalse).head(3)) print(hourly_avg_by_hour.sort_values(ascendingTrue).head(3))我的分析結(jié)果很清晰晚高峰集中在18點到21點峰值出現(xiàn)在20點左右早高峰則小得多只有晚高峰的一半不到。凌晨1點到5點是用電低谷主要負荷基本只有冰箱和待機設備。知道了這個規(guī)律之后我把熱水器的加熱時間調(diào)到凌晨的低谷時段一個月電費下降了約12%這就是數(shù)據(jù)分析直接兌換成錢的例子。4.3 電量與外部因素的關聯(lián)用電量不是孤立的數(shù)據(jù)和溫度、天氣、生活習慣都有關系。盡管我沒有溫度傳感器的數(shù)據(jù)但用本地氣象站的歷史數(shù)據(jù)做了粗略關聯(lián)分析。做法不復雜把日用電量和當天的最高氣溫放進同一個 DataFrame畫散點圖、計算相關系數(shù)。merged pd.merge(daily, temp_daily, ondate) corr merged[kwh].corr(merged[temp_max]) print(corr)在氣溫跨度為-5℃到35℃的全年數(shù)據(jù)里相關系數(shù)大約是0.73說明用電量受氣溫影響非常顯著。而且這個關系不是線性的低于5℃和高于28℃后用電量都會快速上漲中間舒適區(qū)則維持低位。這種非線性特征如果只看月賬單很難察覺但把逐日數(shù)據(jù)一畫圖就非常直觀。5. 可視化呈現(xiàn)與分享要點5.1 用 matplotlib 快速出圖分析過程中我大量依賴 matplotlib因為它在探索階段最靈活改圖成本低。常用的圖有三類:第一類是逐日用電量折線圖過濾掉局部抖動后用滾動平均rolling(window7).mean()畫出平滑趨勢線一眼鎖定季節(jié)變化。第二類是24小時負荷曲線把全年按工作日和休息日分成兩撥分別畫平均曲線色差明顯適合放在數(shù)據(jù)分析報告里說明行為差異。第三類是月度用電量柱狀圖把所有年份的同一個月做對比看是否出現(xiàn)同比異常增長。貼一段我當時畫24小時負荷曲線的核心代碼包含平滑處理效果比直接畫原始折線好很多import matplotlib.pyplot as plt fig, ax plt.subplots(figsize(10, 5)) hourly_avg_by_hour.plot(axax, markero, label小時平均, lw2) ax.fill_between( hourly_avg_by_hour.index, hourly_avg_by_hour - hourly_avg_by_hour.std(), hourly_avg_by_hour hourly_avg_by_hour.std(), alpha0.2, label±1σ ) ax.set_xlabel(小時) ax.set_ylabel(平均用電量(kWh)) ax.set_title(工作日/休息日 24小時負荷曲線) ax.legend()5.2 用 pyecharts 做可交互圖表如果只是在本地自用matplotlib 足夠。但數(shù)據(jù)分享意味著要把結(jié)果發(fā)到群里或嵌到網(wǎng)頁上靜態(tài)圖不方便讀者自己查看細節(jié)這時候我會用 pyecharts 做可交互的 HTML 圖表鼠標懸停能看到具體值還可以縮放平移。pyecharts 的 API 和 ECharts 保持一致畫一個交互式折線圖的核心代碼很短from pyecharts.charts import Line from pyecharts import options as opts line ( Line() .add_xaxis([d.strftime(%m-%d) for d in daily.index]) .add_yaxis(日用電量, [round(v, 2) for v in daily.values], is_smoothTrue) .set_global_opts( title_optsopts.TitleOpts(title家庭日用電量趨勢), datazoom_opts[opts.DataZoomOpts()], ) ) line.render(daily_line.html)這段代碼生成的 HTML 文件可以直接用瀏覽器打開也可以嵌入博客或企業(yè)內(nèi)部系統(tǒng)。我在鄰居群分享時用的就是這種交互圖有幾個人反饋第一次直觀看到家里每個小時耗電這么多比發(fā) PDF 報告有效得多。5.3 分享數(shù)據(jù)時的注意事項既然叫數(shù)據(jù)分享脫敏問題不能忽視。家庭用電數(shù)據(jù)雖然不像身份證號那么敏感但高頻用電曲線其實能反推出家里作息、是否有人、用什么電器私密性并不低。我分享的做法是把時間精度降到日不分享15分鐘級別的原始曲線小區(qū)、樓棟、表號等字段一律不出現(xiàn)別人需要原數(shù)據(jù)時只提供已經(jīng)聚合好的統(tǒng)計結(jié)果比如工作日日均8.5kWh、休息日日均10.2kWh。如果是分享代碼也要順手把數(shù)據(jù)路徑、電表表號、真實地址等寫進代碼或 README 的占位符里。這既是保護自己也是保護看你代碼的人萬一他拿到的是別人的隱私數(shù)據(jù)知道如何處理才正規(guī)。6. 常見問題與排查技巧實錄6.1 時間序列索引的坑時間序列分析最常見的報錯就是KeyError或TypeError原因多半是索引沒有正確設置。pd.to_datetime之后一定要記得set_index(time)否則后面resample會直接報錯。另外如果導出的時間戳帶時區(qū)后綴比如08:00to_datetime解析出來的是帶時區(qū)對象和本地時區(qū)的日期做比較時容易差8個小時我習慣在讀入后直接強制tz_localize(None)去掉時區(qū)信息。6.2 缺失數(shù)據(jù)怎么補才合理我在第3節(jié)提過不要強行補長缺口這里補充一下具體判斷標準。15分鐘粒度的數(shù)據(jù)連續(xù)缺失1-2個采集點即15-30分鐘用前向填充或者interpolate線性插值都能接受。缺失超過兩個小時最好直接在重采樣時跳過因為補出來的數(shù)據(jù)可能抹掉了一個真實的用電行為比如臨時停電后冰箱重新制冷的高功率段。如果缺失的是整天電表通信完全中斷那天就讓它空著畫圖時dropna()掉就行不會對月度匯總造成太大偏差。6.3 幾個能直接抄作業(yè)的小函數(shù)最后分享幾個幾乎每次分析都會用的函數(shù)算是這個項目沉淀下來的小工具def resample_daily(df): 15分鐘/小時粒度數(shù)據(jù)轉(zhuǎn)日匯總 return df[kwh].resample(D).sum().dropna() def rolling_padded(series, window7): 滾動平均并保留前n-1個點的原始值 smoothed series.rolling(window).mean() return smoothed.fillna(series) def peak_hours(df, top_n3): 返回一天中用電最高的N個小時 h df[kwh].resample(H).sum() h h.groupby(h.index.hour).mean() return h.sort_values(ascendingFalse).head(top_n).index.tolist()這些函數(shù)不依賴特定數(shù)據(jù)格式只要你的 DataFrame 有timeDatetimeIndex和kwh兩列就能直接套用。做這個用電量數(shù)據(jù)分享項目前后花了我大概一周的業(yè)余時間最花力氣的不是寫代碼而是把腦子里那些模糊的感覺電費好高變成清晰的量化結(jié)論。分析做完后我不光找出了電費異常的元兇——一臺老化嚴重、保溫性能變差的電熱水器還摸清了自己家的用電習慣順手把熱水器加熱時段調(diào)整到了低谷電價區(qū)間。后來又把這個過程寫成帶交互圖表的分享帖發(fā)到小區(qū)群不少鄰居照著方法排查出自家待機功耗異常的設備。個人體會是數(shù)據(jù)分析本身沒有多玄乎真正有價值的是那份愿意花時間把生活細節(jié)數(shù)字化的耐心。如果你手頭也有一份積灰的用電數(shù)據(jù)不妨按上面的流程走一遍大概率會收獲幾個原來如此的瞬間。本文還有配套的精品資源點擊獲取