ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

电动汽车电池数据实战:pandas清洗、聚合分析与避坑指南

电动汽车电池数据实战:pandas清洗、聚合分析与避坑指南 简介这份电动汽车数据集收录了2025年3K条真实车辆记录覆盖特斯拉、宝马、日产等品牌包含电池化学成分、容量、续航里程、充电标准与速度、价格、产地、自动驾驶等级、安全评级、销量与保修年限等技术规格和销售属性。每行由Vehicle_ID唯一标识适合做车型对比分析、市场趋势研究或机器学习建模训练。数据以2025年最新销售数据为时间锚点并横向涵盖纯电与插电式混合动力车型可支撑从入门数据清洗到进阶特征工程的完整练习。资源包共3个文件含xlsx表格便于筛选透视、csv方便程序读取、json适合接口化调用整包仅492KB轻量易下载。目前已有203人学习对于需要真实车市数据完成课程设计或数据可视化项目的学习者来说是一份紧凑且字段丰富的实用样本。1. 拿到真实汽车数据后的第一件事先搞清它到底能干嘛拿到一份电动汽车数据集时我第一反应不是看有多少条记录而是先确认这些记录是从哪来的。2025 年的 3K 真实记录覆盖特斯拉、宝马、日产三个品牌的电池规格与销售数据意味着你可以直接做三件事按品牌拆电池容量分布、算单位 kWh 的定价基线、拉出 2025 年逐月销售斜率。它适合的人群很具体——做车载电池成本测算的工程师、写新能源汽车行研报告的运营、准备用真实数据训练分类模型的算法岗。我会按数据字段逻辑、pandas 清洗、聚合分析、踩坑清单、进阶验证这条线往下拆新手能照步骤跑熟手可以直接跳到第 4 章对照坑点。2. 电动汽车数据集的字段逻辑电池规格与车型配置怎么对应拿到任何电动汽车数据集第一件事不是急着画图而是把字段之间的对应关系摸清楚。以标题里提到的特斯拉、宝马、日产为例这三个品牌的电池规格记录方式差异非常大直接决定了后面清洗脚本怎么写。我一般会先把一张表拆成三类信息来看电池参数、车型身份、销售事件。这三类信息在原始 CSV 里可能挤在同一行也可能分散在多张表里但最终都要落到一张可分析的宽表上。2.1 电池容量、标称电压与续航三个字段别混着算电池规格字段是所有分析的地基但也是单位最不统一的几个字段。常见记录里会有电池容量、标称电压、电池类型和续航里程其中电池容量大多写着 kWh但总有一批记录给你的是 Ah甚至直接写成“60KWH”这种带单位字符串。标称电压决定 Ah 怎么换算成 kWh公式很简单kWh Ah × V / 1000。同一块电池包350V 平台和 400V 平台换算出的结果能差 14%所以看到 Ah 必须找同行的电压字段找不到就标缺失不要自己假设一个 400V 往里代。续航字段更不能和容量混着看。LFP 磷酸铁锂和三元锂的放电特性不同同样 60kWh 容量放在 Model 3 和放在 Nissan Leaf 上续航能差出 100 多公里。整备质量、风阻系数、BMS 放电策略都会影响这个数字。做分析时如果想从容量估算续航应按品牌和车型细分组单独拟合不要做全局回归全局回归的结果只能用来定性不能用来定量。下面我把最常见的几个电池相关字段列一下方便你拿到数据后先对一遍字段名因为数据集来源不同列名经常叫 battery_capacity_kwh、capacity、pack_size但含义都是电池包总能量。字段常见单位典型取值坑点电池容量kWh / Ah40-100 kWhAh 需乘标称电压换算部分记录带单位字符串标称电压V350-800 V老车型 350V新平台 800V换算时必须配套电池类型枚举NCM / LFP缩写混写如 NMC、磷酸铁锂、LiFePO4 是同一种续航里程km / mi200-600 km标注标准不统一CLTC、EPA、WLTP 数字差异明显电池包版本字符串Standard / Long Range同一车型多个版本是关联销售数据的关键键2.2 车型、电池版本与销售记录怎么串成一张宽表数据商提供的文件我见过两种形态一种是一张宽表每行是一台车电池规格、价格、销售日期都在同一行另一种是拆成两张表一张车型规格表、一张销售流水表。后一种更常见因为电池规格是静态信息销售流水是动态信息分开存储更合理。你把两张表合并时关联键不能只用车系名必须用车型年款加电池包版本。举例说Model 3 在 2024 款里同时有标准版和长续航版一个 60kWh 磷酸铁锂一个 78kWh 三元锂价格差接近一万美元。如果你只按 model_name 去关联销售表系统会把所有 Model 3 的销售记录都匹配到同一个电池版本上后面算价格基线的时候整个分布都会拉宽中位数失真画出来的箱线图里会出现一大堆本不该存在的离群点。正确的做法是建一个复合键brand model_year battery_version确保每条销售记录都对应到唯一一份电池配置。合并完成后我建议把宽表整理成固定的列顺序方便后续脚本复用。列结构大致是vin车辆识别码、品牌、车型名、年款、电池版本、电池容量标准化后、标称电压、电池类型、续航里程、价格、销售日期。注意销售日期粒度很多记录只给到年月没有具体日这种情况下不要硬填 1 号直接在分析里按字符串截取前 7 位转成月度周期反而更干净。这一步做完你手里才真正有一份能直接进 pandas 做统计的数据。3. 用 pandas 跑通 3K 记录的最小分析流程从体检到品牌对比数据表结构确认后下一步是用 pandas 在本地把整个分析流程跑通。我一般按四个步骤走读入与体检、字段标准化、品牌聚合、时间序列拆解。这套流程不挑数据集你以后拿到别的车型数据也能复用。3.1 先做数据体检空值、重复值与单位不统一拿到 CSV 后第一个动作永远是看形状和缺失比例而不是急着画图。3K 记录规模不大pandas 全量读入内存没问题但空值分布直接影响后续填充策略。下面这段代码先把基础信息打出来import pandas as pd df pd.read_csv(ev_data_2025.csv, encodingutf-8-sig) print(df.shape) print(df.dtypes.value_counts()) print(df.isna().mean().sort_values(ascendingFalse))这段代码里我特意用了 utf-8-sig 而不是默认编码因为汽车数据集的 CSV 很多来自国外数据商带上 BOM 头容易让第一列列名多一个不可见字符。df.isna().mean()输出的是每一列缺失值的占比比isna().sum()更好用因为可以直接按比例判断处理策略。我自己的经验阈值是缺失低于 1% 的列直接按行删缺失在 20% 到 30% 之间做成布尔标记列或中位数填充超过 30% 的列基本不要依赖它做结论。单位不统一的处理是体检完之后的重点。假设原始表里 battery_capacity 列有数值、有字符串既有 kWh 又有 Ah我一般写一个标准化函数def normalize_capacity(value, voltageNone): if pd.isna(value): return pd.NA text str(value).strip().upper() if KWH in text: return float(text.replace(KWH, )) if AH in text: if voltage is None or pd.isna(voltage): return pd.NA return float(text.replace(AH, )) * float(voltage) / 1000.0 return float(text) df[capacity_kwh] [ normalize_capacity(v, vol) for v, vol in zip(df[battery_capacity], df[nominal_voltage_v]) ]这里我用了列表推导式而不是apply因为需要同时访问两列的值apply写起来反而绕。Ah 分支下如果拿不到对应电压直接返回pd.NA而不是猜一个典型电压这是血泪经验。你一旦填了个假定电压后面所有按容量做的分组统计都会带着这个系统性偏差而且极难排查。另一个提示数据里可能把 7.5KWh 误写成 75KWh肉眼很难发现。我在做完标准化后一定会按品牌看容量中位数如果某个品牌的中位数值明显超出同车型常识范围就回去翻原始记录。3.2 按品牌聚合电池参数用中位数建基线字段标准化之后最先能出结论的就是品牌维度的电池容量分布。这里的关键选择是用中位数而不是均值。特斯拉车系里高性能版和长续航版的容量明显偏高少数几台车就能把均值拉上去而中位数代表大多数用户实际买到的配置水平。代码很简单brand_stats df.groupby(brand)[capacity_kwh].agg( countcount, medianmedian, meanmean, stdstd ) print(brand_stats.sort_values(median, ascendingFalse))agg里同时算四个统计量count 用来判断样本量是否足够median 做主结论mean 和 std 辅助看离散程度。做完数值统计后我会顺手画一个箱线图比表格更直观import matplotlib.pyplot as plt brand_order [tesla, bmw, nissan] box_data [ df.loc[df[brand] b, capacity_kwh].dropna() for b in brand_order ] plt.boxplot(box_data, tick_labels[Tesla, BMW, Nissan]) plt.ylabel(Battery capacity (kWh)) plt.show()箱线图能一次性暴露三类问题品牌间中位数差异、品牌内部离散程度、异常值。以这类数据集的经验看Nissan 的容量中位数通常明显低于特斯拉和宝马因为主力车型 Leaf 定位入门如果结果完全反过来第一反应应该是回到数据检查品牌映射是不是把车型分配错了。箱线图也能顺带验证 3.1 里单位换算有没有漏网之鱼——如果某个品牌的容量出现一个孤立的高位点多半是混入了一条没做 Ah 换算的记录。3.3 拆出 2025 年销售时间序列看斜率而不是看总量销售数据的分析重点不是总量而是随时间的变化趋势。2025 年逐月销售数据最常见的处理是把日期归一到自然月然后按品牌聚合每月交付或销售笔数df[month] pd.to_datetime(df[sale_date]).dt.to_period(M) monthly df.groupby([brand, month]).size().unstack(brand, fill_value0) print(monthly) smoothed monthly.rolling(3, min_periods1, axis0).mean() print(smoothed.tail())dt.to_period(M)会把日期统一成月份周期对象避免同一天多笔交付造成的日粒度毛刺。unstack(brand, fill_value0)把每个品牌变成一列fill_value0保证没有记录的月份补零否则后面绘图时会出现断线。rolling(3, min_periods1)做三个月移动平均单月促销带来的销量尖峰会被抹掉更适合看中期趋势。注意如果原表里 sale_date 不是日期类型而是字符串pd.to_datetime会自动解析但如果只有年月没有日解析出来的日期会统一落到当月 1 号这不影响月度聚合结果。看趋势不能只靠肉眼最好算一个数值。拿特斯拉为例想确认它 2025 年是否在放量可以用一阶拟合直接得出每月增量import numpy as np x np.arange(monthly.shape[0]) slope_tesla np.polyfit(x, monthly[tesla].values, 1)[0] print(fTesla monthly increase: {slope_tesla:.1f})polyfit的返回值里第一个元素就是线性拟合的斜率单位是“辆/月”。这个数字比“特斯拉销量高”这种描述有用得多因为它可以直接横向对比宝马和日产谁在放量、谁在收缩一目了然。做这一步时要注意样本月份不能太少如果只有三个月数据拟合出的斜率几乎没有参考价值至少要六个月以上再下结论。4. 避坑排查真实汽车数据的五个常见坑现象与原因数据集标题里写着“真实数据”不代表拿到的表是干净的。恰恰相反真实数据最常见的状态是每列都填了值但填进去的内容口径混乱。这一章我把做汽车数据集处理时遇到的高频问题整理成五条每条都按现象、原因、解决三个层次写你在复现时可以直接对照。4.1 车型年款对不上记录年份聚合结果整体偏移现象按 model_year 字段做分组统计发现 2026 款车型在 2025 年的销售记录里出现不少价格还明显偏高年款维度的整体分布向未来偏移。原因汽车行业年款发布时间比日历年份提前。2025 年 8 月就上市 2026 款是常规操作销售表里记录的是实际交易时间车型表里存的是年款标识两个时间概念错位。如果把销售记录按 model_year 归组等于把 2025 年下半年的销量算进 2026 年趋势分析直接失真。解决把两个字段拆开使用销售分析固定用 sale_year配置分析才用 model_year。在清洗阶段加一列df[sale_year] df[sale_date].dt.year所有按时间聚合的逻辑都指向它。年款字段只用来关联车型配置不进时间维度。4.2 电池容量混用总容量与可用容量续航估算直接翻车现象某一品牌电池容量中位数比官方标称值低 6% 到 8%品牌对比图整体下移用容量推算续航的结果系统性偏低。原因数据源里一部分记录填的是电池包总容量一部分填的是可用容量。动力电池出厂时为了防止过充过放BMS 会锁住一部分电量可用容量通常比总容量少 5% 到 10%。不同数据商采集口径不统一导致同一车型出现两个容量簇。解决对每个品牌做容量分布的聚类检查如果同一车型的容量值形成两个相差超过 5% 的簇基本就是口径混用。不要统一乘系数因为你不知道哪条记录是哪种口径。正确做法是按 vin 前缀或电池包代次拆分看是否对应不同生产批次分不清时只做品牌间相对排序不做绝对值对比。这个坑在“真实数据”里出现频率极高而且很难一眼看出因为你看到的数据本身就是“自洽”的。4.3 销售记录混入未交付订单月度曲线虚高现象2025 年某个月销量异常冲高下个月立刻回落到前值一半移动平均线出现一个不自然的尖峰。原因销售表里同时记录了预订订单和已交付订单经销商录入订单的时间是客户下定时不是车辆交付时间。还有一些批次记录是经销商为冲量统一录入整批订单挤在某个月。解决先查表里有没有 order_status、delivery_date 这类字段有就过滤为已交付。如果没有状态字段用价格分布做辅助判断正常交付记录价格集中在指导价附近预订记录往往只有一笔小额订金。仍判断不了就把异常月份标记为待核验不要直接进趋势模型。做月度时间序列时任何超出常规波动幅度的点都要先走这个流程不要急着写进结论。4.4 品牌名与车型名大小写混写groupby 把同一车型拆成两行现象groupby(brand)之后出现 tesla 和 Tesla 两行BMW 和 bmw 同时存在统计结果被拆散。原因数据商多批次导入有的批次字段值全大写有的批次首字母大写前端展示看不出来一到分组聚合就原形毕露。这个问题的隐蔽性在于shape 看起来正常缺失值也少但聚合结果永远对不上。解决清洗第一步就做字符串归一化顺序不能乱。df[brand] df[brand].astype(str).str.strip().str.lower() df[model_name] df[model_name].astype(str).str.strip().str.lower()strip()同时去掉首尾空格和全角空格lower()统一大小写。这一步必须在任何groupby之前执行不然后面所有分组统计都要返工重跑。车型名同样需要处理因为不同批次里 “Model 3” 和 “model3” 极容易并存。4.5 去重只看主键把同配置不同车当成重复删掉现象按 vin 字段去重后记录数减少了几百条但再做品牌分布统计发现原本该有的车型数量对不上。原因vin 在物理车辆层面唯一但同一台车被转售、多次登记时数据商可能在不同时间点各采集了一条。反过来同一型号配置的两台车拥有不同 vin它们不是重复。去重规则没有跟着分析目标走导致有效样本被误删。解决先区分两个场景。做配置统计时按 vin 去重同一 vin 取最新一条记录做交易流水分析时不去重每条销售事件都是独立样本。如果同一 vin 出现在不同月份大概率是转售保留最近一次交付记录。去重之前先看df.duplicated(subset[vin, sale_date, price]).sum()三个字段同时重复才是真正需要删的数据。5. 进阶验证用单位 kWh 价格把数据集用出增量价值这套数据集的增量价值不只是看销量而是把你手里电池规格和销售价格两个维度捏合得到一个业务上真正有用的指标单位 kWh 价格。做法是把裸车价除以电池容量得到每度电多少钱这个数字可以直接用于横向比较品牌间电池成本差异。计算很简单但验证过程才是重点。df[price_per_kwh] df[price] / df[capacity_kwh] baseline df.groupby(brand)[price_per_kwh].agg( medianmedian, q25lambda x: x.quantile(0.25), q75lambda x: x.quantile(0.75) ) print(baseline.sort_values(median))这里我特意同时算了 25 分位和 75 分位单位 kWh 价格的离散度能说明定价策略是统一还是混乱。特斯拉同一电池版本价格相对透明四分位距会收窄宝马如果混入了不同驱动版本区间会明显变宽。拿到结果后用留出法验证随机抽 80% 的记录重算中位数看剩下 20% 是否落在四分位区间内如果大量落在区间外说明分组内还有你没发现的配置混入。实践里我拿到这种数据集最后都会和公开信息做一次对拍。找几个官方公布的车型和电池包配置对比数据集中中位数与公开标称的差值差异在 5% 以内基本可以认为数据可靠超过 15% 就先查币种和是否含税这两个字段是最容易被忽略的。我现在处理汽车数据集的习惯是先花十分钟做三件事确认 sale_date 的粒度归一化品牌大小写检查容量列有没有 Ah 字段。这三件事做完后面所有聚合分析都站在稳的地基上省掉一半返工。希望帮到你。本文还有配套的精品资源点击获取
返回列表