尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Python实现漏电用户自动识别:从数据清洗到异常检测的实战方案

Python实现漏电用户自动识别:从数据清洗到异常检测的实战方案 简介这份电力漏电用户自动识别Python源码包面向电力数据挖掘和异常用电检测场景适合有一定Python基础、正在学习数据挖掘建模或从事用电分析的技术人员。包内基于数据挖掘算法对用户用电数据进行分析通过模式与趋势提取识别潜在漏电用户体现了从数据处理、模型训练到结果可视化的完整流程。压缩包共15个文件主体为1个Python脚本、3个xls数据表、4个npy数据和4个png图表另含pkl/model模型文件和txt导入说明整体仅49KB其中missing_data.xls等数据表对应原始与中间处理结果pkl/npy保存决策树等模型状态png直观展示分类效果目录区分为img、data、tmp等模块结构清晰。目前已有213人学习下载。读者可对照代码与数据逐步理解漏电特征提取、模型参数确定和统计信息生成过程尤其适合作为课程设计、毕业设计或电力数据挖掘入门实践的参考资料。1. 项目概述与实际背景为什么需要“漏电用户自动识别”电力行业的线损管理一直是供电企业的核心考核指标之一而漏电用户的存在就像管道里悄悄漏水一样表面上很难察觉但每个月汇总线损报表时数字会诚实地告诉你出了问题。我以前在基层供电所待过一段时间每到月底对账最头疼的就是那些“线损异常台区”——台账上用户数量和电量都对得上但台区总表和分户表之和就是差着一截。逐个排查一个台区几百户挨家挨户摇表测绝缘人力成本和停电影响都扛不住。这个用Python写的“电力漏电用户自动识别”源码本质上是把老师傅的排查经验转化成一套可复用的算法流程。它不依赖额外硬件不需要装漏电监测终端而是从用电信息采集系统里已有的数据出发——比如日冻结电量、电流曲线、电压曲线——通过数据挖掘的手段把“疑似漏电用户”从几十上百户里筛出来缩小人工复测的范围。换句话说它解决的是“先查谁、重点查谁”的问题把排查效率从“大海捞针”提升到“按图索骥”。这个项目适合三类人看一是供电公司的线损管理人员想用低成本方式提升异常排查效率二是做电力数据分析的开发者想学习业务规则如何转化为代码逻辑三是Python初学者想找一个完整的、能落地的数据分析项目练手。源码里涉及数据清洗、特征构造、规则判定和简单的可视化输出层级清晰改造空间也大。2. 整体设计与核心思路拆解2.1 为什么选择Python而非传统计量手段传统漏电检测靠的是现场仪器比如钳形电流表测漏电流、绝缘电阻测试仪测对地绝缘精度高但只能“点到点”排查无法做面上一轮初筛。而漏电用户的用电数据其实是有迹可循的——对地泄漏电流会导致火线和零线电流不相等反映在智能电表上就是“电流不平衡”漏电严重的用户在不用电的时段比如深夜依然会有微小电流消耗反映在电量曲线上就是“夜间底电流异常抬升”。Python在这个场景里最大的优势不是算法多先进而是数据处理的工程效率高。pandas处理几万行日冻结数据非常轻松numpy做向量化计算也不需要写循环加上sklearn提供现成的聚类和异常检测模型整个过程不需要重型开发框架一台普通办公电脑就能跑。相比起用C或Java从零实现Python的开发周期可能压缩到原来的三分之一。2.2 识别逻辑的三种思路规则、统计与模型这套源码的识别逻辑我拆解下来实际上是三条路线并行最终综合打分规则线路硬性阈值判断。比如“三相电流不平衡度超过30%”“夜间两小时平均电流超过基准值3倍”这类业务上约定俗成的红线直接触发告警。统计线路基于台区横向对比。同一台区下正常用户的用电曲线形态有相似性通过计算每个用户与台区均值的偏离程度比如z-score超过2个标准差的就被标记为异常样本。模型线路利用无监督学习做聚类。把用户按“用电量级、曲线波动性、夜间行为”等特征聚类孤立点或小簇用户往往是异常候选。为什么要做三条线而不是只用一个算法因为漏电现象在数据上的表现并不唯一——有的是持续漏电长期底电流偏高有的是间歇性漏电只在特定时段泄漏有的还叠加了窃电因素电流曲线有明显的人为扰动。单一规则只能覆盖其中一种模式三条线交叉验证才能把召回率提上去又不会让误报率高到没法用。2.3 源码整体流程从数据到名单整体流程可以概括为五个环节数据读取与校验、清洗与归一化、特征构造、异常评分、结果输出。源码的目录结构设计得比较清晰便于二次开发leakage_identify/ ├── data/ │ ├── raw/ # 原始数据目录日冻结、电流曲线 │ └── processed/ # 中间处理结果 ├── src/ │ ├── data_loader.py # 数据加载与格式校验 │ ├── preprocess.py # 清洗、去重、缺失值处理 │ ├── features.py # 特征工程夜间电流、不平衡度等 │ ├── detector.py # 三条识别线路的核心逻辑 │ └── report.py # 结果汇总与Excel导出 ├── config.yaml # 阈值与参数配置 └── main.py # 主入口这种模块化设计的好处是业务人员可以只调config.yaml里的参数不需要动代码开发者想替换算法也只需要改动detector.py一个文件。我当时接手这类项目时最怕的是一大坨代码全部堆在main.py里调一个阈值都要翻半天这个结构算是给出了一个不错的示范。3. 核心细节解析与实操要点3.1 数据准备哪些数据字段最关键我最开始误判了一个问题以为漏电识别只需要看“电量”这一个字段后来真正跑到数据里才发现电量是累计值一天一个数信息量太小根本看不出“深夜底电流”这种瞬时特征。真正好用的是下面几类字段电流曲线数据最好是15分钟或30分钟一个采集点的分相电流A/B/C三相这是判断不平衡度最直接的输入。电压曲线数据漏电严重时由于漏电流分压用户端电压在负荷低谷期会异常偏高对地绝缘下降导致泄漏电流分走了本该回流的电流。日冻结正反向有功电量反向电量出现异常增量提示可能存在电压异常或接线问题。台区ID和时间戳用于横向对比和按台区聚合没有这两个字段后续的“台区内横向比较”就无从做起。数据格式建议统一为如下结构源码里已经预设了字段名映射但实际接入不同厂家采集系统时字段名大概率要改这个适配工作在项目初期是逃不掉的meter_id, dt, phase_a_current, phase_b_current, phase_c_current, voltage, active_energy 1001, 2024-01-01 00:15:00, 2.35, 2.28, 2.31, 221.5, 12345.6 1002, 2024-01-01 00:15:00, 1.12, 0.98, 1.05, 219.8, 6789.13.2 数据清洗容易被忽视的“脏数据陷阱”有一次我跑完整个流程输出结果里有好几个用户被标成“重度异常”派人去现场核查结果发现那几户根本没人住电表是停用的。回头看数据原来是采集系统在电表停用后依然每隔15分钟补了一条零值数据零值曲线和正常曲线差异巨大自然被模型判成了异常簇。所以清洗环节绝不只是一句“dropna()”就完事儿。至少要做以下几件事去重同一个表计在同一采集时刻出现多条记录保留采集质量标志最优的一条。零值处理连续零值超过96个采集点即24小时的判断为“表计停用”直接剔除出分析样本。缺失值填充单点缺失用前后值的线性插值大段缺失超过连续30分钟则丢弃该日数据避免插值引入虚假特征。极值截断电流值超过额定值3倍以上的大概率是采集异常而非真实漏电这类点应该做截断而不是参与计算。这个阶段输出的“清洗报告”很重要——记录每个台区剔除了多少用户、多少数据点、为什么剔除方便后续审计。业务部门看到清洗逻辑清晰对结果的信服度也会高很多。3.3 特征工程把“漏电”翻译成数字特征特征工程是整个项目的灵魂规则和模型都是基于特征来跑的。我整理了一下源码里构造的六类核心特征每类特征都对应具体的漏电物理表现特征名计算方式对应物理含义相间不平衡度最大相电流-最小相电流/最大相电流单相接地漏电会导致某相电流显著偏低夜间底电流均值02:00-05:00电流均值睡眠时段本应接近零负荷若明显偏高则疑似漏电底电流波动率夜间电流标准差/均值间歇性漏电会体现为夜间电流忽高忽低功率因数异常度平均功率因数与台区均值偏差漏电会导致无功损耗增大功率因数下降电压抬升指数夜间电压均值与白天均值比值漏电时轻载段电压异常升高电量突变系数近7日电量与前期30日电量均值比漏电恶化时电量会阶梯式上升这些特征里夜间底电流均值效果最直接——漏电的物理本质就是“电流不经过正常回路直接入地”无论漏电点在用户侧还是表后线夜间负荷最小时最能暴露问题。但要注意农村台区有些用户养鱼、养殖夜间增氧机一直在运转这类用户的夜间电流天然就高所以在做台区横向比较时要识别“正常高负荷用户”避免一刀切误伤。3.4 检测算法三条路线的融合判定策略规则线路中的阈值不能拍脑袋定我在运行源码时试过直接套用默认阈值结果误报率高得离谱。后来梳理了历史已确认的漏电案例用“已知异常用户”反推阈值——比如已知20户漏电用户的“不平衡度”分布在25%到60%之间其中70%超过30%那把阈值定在30%就是合理的。这种“用历史数据标定阈值”的做法比理论推导靠谱得多。统计线路中z-score计算要注意台区样本量。如果某个台区只有十来户均值和标准差本身就不可靠我会做一个小处理当样本数小于30时改用中位数和MAD绝对中位差替代均值和标准差抗干扰能力强不少。模型线路中源码默认用的是DBSCAN聚类。“为什么不是KMeans”因为KMeans需要预先指定簇数而实际台区里正常用户有几类、异常用户有几类事先根本不知道。DBSCAN的好处是不用指定簇数只用给定邻域半径eps和最小样本数min_samples它能自动识别“不属于任何簇”的孤立点这正是我们要找的异常候选。eps参数我一般从0.5开始调然后看聚类结果中的孤立点占比——如果超过10%说明eps太小正常用户都被切成了碎片如果孤立点不足1%说明eps太大异常被吞进正常簇了。三个通道各自输出一个“异常分”最后加权融合。我实测下来的权重参考值是规则0.4、统计0.3、模型0.3理由是规则线路直接对应业务红线可信度最高统计和模型作为补充主要抓规则覆盖不到的模式。这个权重在config.yaml里可以调不同台区性质城市台区/农村台区/商业综合体可以分别保存一套参数。4. 实操过程与核心环节实现4.1 环境准备Windows下跑通的最小配置源码是纯Python工程不依赖Linux环境。我建议用Python 3.9以上版本原因是最新版的pandas和scikit-learn已经逐步放弃对3.8的支持没必要在旧版本上折腾。依赖库装这几个就够pip install pandas numpy scikit-learn pyyaml openpyxl这些库分别负责数据表处理、数值计算、机器学习、配置文件读取和Excel结果导出。在我的测试机上i5处理器、16GB内存、机械硬盘处理一个包含500户、每户96个采集点的台区数据全流程跑完大约15秒性能瓶颈主要在磁盘IO换成固态硬盘可以压到5秒以内。如果你要同时处理几百个台区建议用multiprocessing做并行源码里预留了进程池接口只是默认没开启。4.2 配置参数必须手工调整的四个关键项打开config.yaml最关键的四个参数我逐个说明一下threshold: unbalance: 0.30 # 相间电流不平衡度阈值 night_current: 3.0 # 夜间底电流疑似阈值单位A voltage_rise: 1.08 # 夜间电压抬升指数阈值 model: eps: 0.5 # DBSCAN邻域半径 min_samples: 5 # 最小簇样本数 outlier_ratio: 0.05 # 孤立点占比合理性参考 weight: rule: 0.4 statistic: 0.3 model: 0.3unbalance阈值取0.3意味着最大相电流与最小相电流相差超过30%才触发规则。如果你们台区三相负荷本来就不平衡这个值可以放宽到0.4否则会有一批正常用户被误伤。night_current3A在220V单相回路里对应约660W负荷如果你管理的台区以纯居民为主这个值偏高了建议先统计所有用户夜间电流的95分位数取分位数的1.5倍作为阈值更贴合实际数据。eps这个值的物理意义是“两个样本在多远距离内算邻居”取决于你做特征归一化时用的是什么方法。如果用的是StandardScaler标准化eps0.5是一个安全的起点如果用了MinMaxScaler距离范围被压缩到0到1之间eps建议调到0.1到0.3之间。weight三个权重加起来要等于1这个不用多说。关键是调完权重后要回验历史已确认的漏电案例看综合分排名是否把已知异常排到了前列。4.3 核心代码走读detector.py里的关键步骤我把detector.py里最核心的规则判断部分摘出来加上注释说明def rule_detect(df): 规则线路检测 df: 包含相电流、夜间电流等特征的DataFrame 返回: 每个用户的规则异常得分0到1 score np.zeros(len(df)) # 1. 相间不平衡度超阈值记0.4分 unbalance_ratio (df[[a_cur, b_cur, c_cur]].max(axis1) - df[[a_cur, b_cur, c_cur]].min(axis1)) / \ df[[a_cur, b_cur, c_cur]].max(axis1) score (unbalance_ratio cfg[threshold][unbalance]).astype(float) * 0.4 # 2. 夜间底电流超阈值记0.3分 score (df[night_current] cfg[threshold][night_current]).astype(float) * 0.3 # 3. 电压抬升指数超阈值记0.2分 score (df[voltage_rise] cfg[threshold][voltage_rise]).astype(float) * 0.2 # 4. 电量突变系数超过1.5记0.1分 score (df[energy_surge] 1.5).astype(float) * 0.1 return score / 1.0 # 归一化到0到1这段代码的思路是“累加计分”每命中一个规则就累加对应的分数最终分数越高异常置信度越大。实际运行中我建议把得分超过0.7的用户列为“重点核查对象”0.4到0.7列为“关注对象”。这里有一个注意点unbalance_ratio的分母用的是最大值如果三相电流都接近0比如用户长期不用电这个比值会变成0/0的NaN程序会报错或给出错误结果。所以在计算之前要加一个过滤条件把三相电流最大值小于0.1A的用户先剔除掉。4.4 结果输出与Excel报表设计识别结果通过report.py导出为Excel里面包含三张表异常风险排名按综合得分降序排列列出表计ID、所属台区、各特征值、各通道得分、综合得分方便直接按排名分配工单。特征明细展示每位用户的关键特征原始值用于人工复核时查证。清洗日志记录每个台区剔除的数据点和原因方便审计。Excel和CSV的区别在于Excel可以做多sheet还支持单元格自动筛选老师傅拿到文件后直接按综合得分排序从上往下逐户核查就行不需要任何技术基础。导出时我习惯用openpyxl加一个条件格式综合得分0.7的标红底0.4到0.7的标黄底扫一眼就知道优先级。5. 常见问题与排查技巧实录5.1 误报率过高现场核查全是“正常用户”这是我最常遇到的问题通常有三个原因阈值设置不合理。我之前用默认的0.3不平衡度和3A夜间电流阈值在某个农村台区跑出来40%的用户都“异常”后来发现那边很多用户装了三相动力电磨面机、水泵启动瞬间电流波动极大平均值自然就“超标”了。解决办法是分台区类型设置阈值居民台区用严格阈值农综台区用宽松阈值。数据里的“正常高负荷用户”被当成异常。有些用户家里开小卖部、做夜宵夜间用电量天然比其他人大。这类用户的特征是夜间电流虽然高但曲线平稳、波动率低和漏电的“忽高忽低”特征不一样。解决办法是在特征工程里加入波动率指标看到“夜间电流高但波动率低”的样本把规则得分降权。台区户变关系不对。数据里用户的台区归属字段是错的——用户实际在A台区但系统里挂在B台区导致横向比较时他成了“异类”。这个很难通过算法解决只能靠现场核对档案或者用电压曲线相关性聚类来校验户变关系。5.2 漏电用户一个都识别不出来全台区“正常”漏报比误报更麻烦因为误报顶多是浪费人力漏报是彻底失去价值。我遇到过一次排查后发现是数据粒度的锅——那批数据是“日冻结电量”根本没有日内电流曲线我的算法里几乎一半特征构造不出来只剩一个“电量突变系数”在孤军作战识别不出来也是正常的。后来又遇到一种情况某台区所有用户的“夜间电流”都是0。起初以为是漏电不存在后来说道采集终端设置有问题深夜数据上报策略是“无变化不上报”导致凌晨的电流值全是补零。这个情况要从源头解决联系采集主站调整上报策略或者改用“功率曲线”等替代数据源。还有一种可能是漏电点不在用户侧而在台区到用户之间的线路上。这种漏电在用户表计上体现不出来所有户内特征都正常但台区总表能看到异常损耗。这种情况需要转换思路从“用户侧识别”改为“台区线损异常诊断”从总表的电流曲线和电压曲线入手判断漏电区段。5.3 内存不足处理万户级台区时直接卡死单个台区动辄几百户但整治“串台区”或“多台区合并”时数据量可能到上万户。直接用pandas全量读入内存可能爆掉。我的处理方案是分块处理加特征聚合chunk_size 2000 results [] for chunk in pd.read_csv(all_data.csv, chunksizechunk_size): # 对每一块数据做特征提取 chunk_features extract_features(chunk) results.append(chunk_features) # 最终合并特征结果 final_df pd.concat(results, ignore_indexTrue)另外建议所有中间DataFrame在用完后显式删除并调用gc.collect()。Python的内存在大数组操作后不会立刻返还给操作系统攒多了就会让系统变得很卡很多内存问题其实是“内存碎片”造成的不是真的不够用。5.4 模型参数调优DBSCAN的eps怎么快速定前面说eps从0.5起步但具体怎么调我有个实用技巧先跑一次KNN距离图。计算每个样本到其第k个最近邻的距离k取min_samples把这些距离排序画出来曲线出现“拐点”的位置就是在曲线拐弯处对应的距离值那就是合适的eps。这个方法在sklearn的KNeighborsTransformer里可以直接实现不用额外装库代码量也就十几行。不过坦白说在实际业务里我很少把eps调到极致精确。因为漏电识别最终还是要靠人工复核算法只需要把“大概率的异常”排在前面就行不必追求统计上的完美分类。我在现场和老师傅交流时经常说这个工具是给师傅们“减少排查范围”的不是“替代现场判断”的。认清这个定位就不会在算法精度上钻牛角尖了。6. 最终使用建议与扩展方向按照这套源码和配置流程跑下来我在自己负责的试点台区里做到了“异常用户命中率约六成”——也就是说按综合得分从高到低排查时前十户里能确认出六户左右存在漏电或疑似漏电问题。这个命中率谈不上惊艳但相比原来的“盲查”同样时间能覆盖的范围大了好几倍。实际使用中我还发现了一个额外价值这套流程不只是拿来识别漏电它输出的特征数据稍作改动就能用来做“台区窃电嫌疑排查”“集中器采集异常诊断”“三相不平衡治理辅助决策”。举个例子识别漏电时特别关注的“相间电流不平衡度”特征在治理低电压台区时同样有用可以快速找出“变压器出口三相不平衡最严重的台区”优先安排换相施工。最后分享一个我踩过几次坑后总结出的建议拿到任何一套类似的源码第一件事不要急着跑通全部流程而是准备好一份“带标签的历史数据”——也就是过去几年确认过的漏电用户名单以及他们的采集数据。用这份数据做回测把阈值和权重调到一个合理的起点再让模型去处理没有标签的新数据。没有回测就上线出来的结果你很难判断是算法有效还是数据巧合。这一点适用于任何数据挖掘项目不只是漏电识别。本文还有配套的精品资源点击获取
返回列表