
前几天朋友丢给我一份销售数据让帮忙看看哪个产品卖得好。我打开一看血压上来了日期三种格式混着写金额前面挂着¥还带着逗号产品名iPhone有六种写法缺失值、重复行一个不少。这种数据你直接 groupby算出来的全是错的。今天这篇就干一件事把这份脏数据洗干净再画出能看的图。代码 40 行复制就能跑。环境很简单pandas 2.x 加 plotly。没装的跑一行 pip install pandas plotly。版本这块提一句pandas 2.x 里 to_datetime 处理混合日期格式要加 format“mixed”1.x 不用。这个坑后面细说先记住。先看数据长什么样。真实场景你是从 CSV 读我这里用代码造一份同样脏的数据效果一样。df.info 和 isna().sum 先跑一遍心里有数215 行里 region 缺了 32 个qty 缺了 11 个还有 15 行是重复的。import numpy as np import pandas as pd # 造一份脏数据模拟业务系统导出的常态 rng np.random.default_rng(42) n 200 df pd.DataFrame({ product: rng.choice( [ iPhone, IPHONE, MacBook , macbook, AirPods, airpods ], n), date: rng.choice( [2026/01/05, 2026-01-06, 01-07-2026, 2026/1/8], n), amount: [¥ f{x:,} for x in rng.integers(3000, 15000, n)], qty: rng.integers(1, 5, n).astype(float), region: rng.choice([华东, 华南, 华北, None], n, p[0.3, 0.3, 0.25, 0.15]), }) # 混入缺失、重复、脏值 df.loc[rng.choice(n, 20, replaceFalse), amount] N/A df.loc[rng.choice(n, 10, replaceFalse), qty] np.nan df pd.concat([df, df.iloc[:15]], ignore_indexTrue) # 15 行重复 print(原始形状:, df.shape) print(缺失统计:\n, df.isna().sum())接下来一步步洗。先洗产品名 iPhone和IPHONE在机器眼里是两个东西一行 str.strip().str.lower 解决六种写法变三种。日期是重灾区2026/01/05和01-07-2026混在一起pd.to_datetime 直接转会报错pandas 2.x 加 format“mixed” 让它自己认格式。金额那一列是字符串先把¥和逗号替换掉再用 pd.to_numeric 转数字errors“coerce” 让转不过来的N/A变成 NaN 而不是报错脏值多的列全靠它。# 洗产品名大小写空格统一 df[product] df[product].str.strip().str.lower() # 三种日期格式统一 df[date] pd.to_datetime(df[date], formatmixed) # 金额去符号转数字N/A 变 NaN df[amount] (df[amount].str.replace(¥, , regexFalse) .str.replace(,, , regexFalse)) df[amount] pd.to_numeric(df[amount], errorscoerce) # 去重 缺失处理 df df.drop_duplicates().copy() df[qty] df[qty].fillna(df[qty].median()) df[region] df[region].fillna(未知) print(清洗后形状:, df.shape) print(缺失统计:\n, df.isna().sum())洗完 200 行缺失清零。groupby 一看macbook 卖了 62 万airpods 53 万iphone 49 万。plotly 两行画出柱状图和趋势线write_html 存下来浏览器打开就能看。import plotly.express as px sales df.groupby(product, as_indexFalse)[amount].sum().sort_values(amount) print(sales) trend df.assign(daydf[date].dt.date).groupby(day, as_indexFalse)[amount].sum() fig1 px.bar(sales, xproduct, yamount, titlesales by product) fig1.write_html(bar.html) fig2 px.line(trend, xday, yamount, titledaily sales trend) fig2.write_html(line.html)再说三个坑都是我真踩过的。第一混合日期格式pandas 1.x 和 2.x 写法不一样抄旧教程的代码会报错认准 format“mixed”。第二链式赋值警告drop_duplicates 之后加个 .copy() 最省事。第三groupby 里直接用 df[“date”].dt.date 做分组键pandas 2.x 会吞掉列名先 assign 成一列再分组。这套流程我每次拿到新数据都跑一遍收藏这篇下次照着做省半小时。下期数据分析实战第2期讲 groupby 之后怎么做透视表和环比关注我不错过。你们平时拿到最脏的数据长什么样评论区说说。Cyrus