不用装什么高端设备,也不用迷信那些收费软件,你手头只要有Python和Pandas,就能搞定大部分数据分析的活儿。今天这篇就把我平时处理数据的完整套路拆开讲,从读数据、洗数据到画图,一条龙走完,最后附上一个可以直接改改就用的实战案例。
先说清楚这篇文章是写给谁看的:一是刚接触数据分析、被各种教程绕晕的初学者,二是会用Excel但想提升效率、面对几十万行数据就卡死的办公族,三是有一定Python基础、想系统梳理Pandas数据清洗和可视化流程的从业者。读完你能收获一套可复用的分析框架,以后拿到任何表格数据,都知道第一步干什么、第二步干什么、哪些坑必须绕开。
1. 先别急着写代码:Pandas数据分析的整体思路
1.1 为什么是Pandas,而不是Excel或SQL
很多人问我,Excel那么方便,SQL也能查数据,为什么非得学Pandas?我的回答通常是:看数据量和使用场景。
Excel在5万行以内确实顺手,可一旦到了几十万行,公式拖拽就卡到怀疑人生,更别提做复杂清洗时手动操作的重复劳动。SQL擅长的是数据库内的聚合查询,但数据清洗能力相对薄弱,很多字符串处理、正则匹配、按复杂规则填充缺失值的操作,写起来非常绕。Pandas的好处在于,它是内存中的DataFrame,既能像Excel一样直观做筛选和修改,又能像SQL一样做分组聚合,还顺手把Python的编程能力带进来了。一个几十万行的CSV文件,Pandas读进来几秒钟,清洗逻辑用代码写清楚后一劳永逸,下次来新数据直接重跑一遍脚本。
另外,Pandas和Excel、SQL并不互斥。我日常工作里常见的是:数据从业务系统导出为Excel,先用Pandas清洗整合,再把结果写回数据库或者生成可视化报表。各干各擅长的事,效率最高。
1.2 一套可复用的分析流程
我做了这么多个数据分析项目后,总结出一套固定的流程,不管拿到什么数据,都按这个节奏走:
- 读取数据,先看结构:列名、行数、每列的数据类型。
- 全面体检,识别脏数据:缺失值、重复值、异常值、格式不一致。
- 按规则清洗,建立干净数据集:填充或删除缺失、去重、类型转换、字符串规范化。
- 探索分析,寻找规律:分组聚合、透视表、多表关联,计算关键指标。
- 可视化验证,表达结论:用图表快速验证假设,输出报告。
这里面最容易翻车的是第二步和第三步,因为“脏数据”的形态太多了,同样是手机号,有的带横杠,有的不带;同样是日期,有的是字符串,有的是时间戳。清洗不是机械地套函数,而是先想清楚“这份数据要用来解决什么问题,哪些字段的质量会影响结论”。我见过太多人一上来就dropna,把有用信息也删没了,这个后面详细说。
2. 环境准备与工具选型
2.1 安装Pandas这件事,其实有不少坑
Pandas的安装本身不难,难的是安装完以后环境和依赖搞出问题。最推荐的方式是用Anaconda装Python,它自带Pandas、Matplotlib、Jupyter等常用库,省去逐个安装的麻烦。不过如果你已经装了官方Python,那在命令行执行下面这行就行:
pip install pandas matplotlib seaborn openpyxl这里有个细节很多人会踩:读Excel文件时,光装Pandas是不够的,还需要openpyxl库(对.xlsx格式)和xlrd库(对旧版.xls格式,不过新版本xlrd只支持.xls了)。我当年第一次用pd.read_excel报错,就是因为没装openpyxl。所以上面这条命令里我把openpyxl一起装上了。
PyCharm用户注意一下,用PyCharm装包的时候要看清解释器路径。我见过有人电脑里有三四个Python,PyCharm用的解释器和命令行用的不是同一个,结果命令行里能用Pandas,PyCharm里import直接报错。解决办法是在PyCharm的Settings里找到Project Interpreter,确认当前解释器路径,再用下方的加号搜索安装Pandas,这样保证装进了同一个环境。
如果你用的是VSCode,那更简单,直接在终端里用pip装,然后记得选择正确的Python解释器即可。建议用conda创建一个独立环境,别把不同项目的依赖混在一起,这是做数据分析项目的基本卫生习惯。
2.2 配套工具的选择与建议
写数据分析代码,我常用的组合是Jupyter Notebook加PyCharm互补。探索阶段在Jupyter里一行一行跑,能立刻看到结果,尤其是DataFrame的表格渲染,非常直观;正式做项目时用PyCharm,代码结构清晰,方便调试和复用。
很多刚入门的朋友喜欢问“用哪个IDE好”,其实工具对你输出结果的影响远小于你对数据本身的理解。我建议不要在工具上花太多时间纠结,Jupyter最合适起步,等代码逻辑稳定后再迁到脚本里。
另一个容易忽略的点是数据可视化辅助工具。如果你后续要对接企业级的可视化大屏或者报表需求,可以把Pandas清洗后的结果导出给专业可视化工具,比如用to_excel或to_csv导出,再导入报表工具做成大屏效果。Pandas做的是数据预处理和初步图表分析,专业大屏交给专业工具,两者配合才是完整链路。
3. 数据读取与初始探查
3.1 读取文件时最容易被忽略的参数
读CSV文件,90%的人只用pd.read_csv("文件名.csv")就完事了。这么做在数据规范时没问题,但实际工作中一定会遇到编码问题。国内Excel另存的CSV文件,默认是GBK编码,Pandas默认按UTF-8解析,一跑就报UnicodeDecodeError。解决办法很简单:
import pandas as pd df = pd.read_csv("销售数据.csv", encoding="gbk")还有CSV文件的列分隔符,如果数据里字段本身包含逗号,就常见用制表符或分号分隔,这时候要指定sep参数。另外,如果文件第一行不是列名,要传header=None并手动指定列名:
df = pd.read_csv("data.csv", header=None, names=["订单号", "日期", "金额"])读Excel文件同样有讲究。一个工作簿里常常有多个Sheet,只读某个Sheet要写:
df = pd.read_excel("销售数据.xlsx", sheet_name="华东区", engine="openpyxl")我在实际项目里还经常遇到这种情况:Excel的“表头”前面空了好几行,真正的列名在第4行。这时候可以用skiprows参数跳过头几行,再配合header参数指定列名行,基本都能准确读入。
3.2 拿到数据后先做的三件事
数据读进来后,别急着清洗,先做三件事了解数据全貌。第一是看行列规模,第二是看字段类型,第三是看整体分布。
# 1. 查看行列数 print(df.shape) # 2. 查看列名和数据类型 print(df.dtypes) # 3. 查看前5行 print(df.head()).info()方法也很实用,它会一次性把行数、列数、每列的非空值数量及数据类型列出来,我拿到任何数据都会先跑一下:
df.info()这一步能帮助快速定位缺失严重、类型不对的列。比如某列显示object但里面其实是数字,某列显示float64但很多是NaN,都会在这里露出马脚。接下来再用df.describe()查看数值列的统计量,包括均值、标准差、最小最大值、四分位数,一眼就能发现异常值存在的痕迹。
有个经验分享:describe()里如果某个字段的max和75%分位相差特别悬殊,该字段大概率有离群值。比如“销售额”的75%分位是500,max却是50000,那这个50000就值得查一下是真实业务还是录入错误。
4. 数据清洗实战:把脏数据变成能用的数据
4.1 缺失值处理:先搞清楚为什么缺失
缺失值处理是最容易“好心办坏事”的环节。先别急着删除或者填充,得先想清楚缺失的原因。
用df.isnull().sum()可以查看每列的缺失情况。如果一个字段缺失比例超过50%,且这个字段对分析结论不重要,果断删掉整列更省事;如果一个字段只有个别缺失,那要看缺失是否有规律。比如用户填写表单,收入字段经常为空,这种缺失往往是用户主动不填,在分析用户特征时应该单独归为“未知”类别,而不是简单用均值填充。
填充方法分几种场景:
- 数值列,且数据平稳无趋势:用均值或中位数填充。中位数对异常值更稳健,我更常用。
- 时序数据,短期波动不大:用前向填充法,也就是用上一个有效值填充缺失,Pandas里写method="ffill"。
- 类别字段:用众数填充,或者额外标记“缺失”作为一个类别。
# 均值填充 df["销售额"].fillna(df["销售额"].mean(), inplace=True) # 中位数填充 df["销售额"].fillna(df["销售额"].median(), inplace=True) # 前向填充 df["日期"].fillna(method="ffill", inplace=True) # 类别字段填众数 df["地区"].fillna(df["地区"].mode()[0], inplace=True)删除行的方法我建议保守使用,尤其是当缺失值总量不大、且缺失的行在其他字段上有重要价值时。但有一种情况必须用dropna:这一行缺失了所有核心字段,留着只会干扰后续分析。df.dropna(subset=["订单号", "销售额"], how="all")这种写法比较精准,不会误删。
注意:inplace=True这个参数在不同的Pandas版本里行为有微调,新版里某些方法会提示以后将废弃。我更推荐写成df = df.fillna(...)这种赋值方式,不容易产生歧义。
4.2 重复数据与异常值:别让脏数据带偏结论
重复数据处理逻辑相对直接,但有一个细节必须说。df.duplicated()默认判断整行所有列都相同才算重复,可实际业务里,往往只需要根据订单号或ID判断。比如同一个订单号在明细表里可能对应多条记录,那是正常的多行明细,不能删;但如果是同一笔订单被重复导出了两次,那就要按订单号去重。
# 按订单号判断重复 df[df.duplicated(subset=["订单号"], keep=False)] # 删除重复记录,保留第一条 df.drop_duplicates(subset=["订单号"], keep="first", inplace=True)异常值识别的思路上升到统计层面会更有据可循。最基础的是用箱线图法,按四分位距(IQR)划定上下限,超出限值就视为异常。这个方法不要求数据服从正态分布,适用面广。代码可以自己写:
Q1 = df["销售额"].quantile(0.25) Q3 = df["销售额"].quantile(0.75) IQR = Q3 - Q1 lower = Q1 - 1.5 * IQR upper = Q3 + 1.5 * IQR df_outlier = df[(df["销售额"] < lower) | (df["销售额"] > upper)]更严格的场景可以用Z-Score法,但前提是数据近似正态分布。数据分布明显偏态时,可以先做对数变换再检测。这里要给一个实操提示:异常值不等于错误值,它可能是真实业务中的特殊情况,比如大客户的一笔大额订单。所以检测出异常值后,先结合业务背景判断是录入错误、特殊业务还是正常波动,再决定剔除还是保留。无条件删异常值的人,很容易把业务里的关键信息也删了。
4.3 数据类型转换与字符串清洗
类型不对是数据分析最常见的坑。最经典的场景是把日期读成了字符串,把金额读成了带千分位逗号的文本。前者导致无法排序和按月聚合,后者导致无法做数值运算。处理思路就一句话:让Pandas知道你这份数据的真实类型。
日期类型用pd.to_datetime,它特别智能,能自动识别很多日期格式,但遇到“2023年1月5日”这种中文字符串时还是需要手动指定format:
df["日期"] = pd.to_datetime(df["日期"], format="%Y年%m月%d日")数值转换用pd.to_numeric,遇到无法解析的值设为NaN然后统一处理:
df["金额"] = pd.to_numeric(df["金额"].str.replace(",", ""), errors="coerce")字符串清洗在数据治理里同样重要。很多数据源自人工录入,姓名前后带空格、电话带横杠、大小写不统一、文本里混入换行符。我的处理套路是:
# 去除首尾空格和特殊字符 df["姓名"] = df["姓名"].str.strip() # 统一去除电话里的横杠和空格 df["电话"] = df["电话"].str.replace(r"[- ]", "", regex=True) # 统一大小写 df["邮箱"] = df["邮箱"].str.lower() # 提取日期字符串里的年份 df["年份"] = df["日期"].str.extract(r"(\d{4})")正则表达式在这个环节简直救命。比如需要从“苹果 iPhone 15 Pro 256G”里提取品牌和型号,一个str.extract配合正则就完成了,效率远高于逐行手动处理。
5. 数据聚合与分析:从“看到”到“看懂”
5.1 groupby与agg的配合使用
数据清洗干净后,接下来就是怎么把信息提炼出来。groupby就是Pandas里的“数据透视核心”,它做的事情和Excel里的数据透视表本质一样。按某个字段分组,再对另一列做聚合运算。
举一个实际例子:手上有一份全国各城市的门店销售数据,需要按省份统计总销售额、订单数和平均客单价。
result = df.groupby("省份").agg( 总销售额=("销售额", "sum"), 订单数=("订单号", "count"), 平均客单价=("销售额", "mean") ).reset_index()这里有几个细节值得注意。
agg里面用元组指定列名和聚合函数,是新版Pandas推荐的方式,可读性很强。执行完后分组字段会变成索引,如果需要保持为普通列,加上reset_index()。我见过不少人因为忘记这一步,后续想要筛选省份时操作很别扭。
如果要对同一列做多个聚合,可以直接传入一个列表,结果会自动生成多层列名,用起来稍微麻烦一点,我一般会在agg后用columns属性设置列名:
result = df.groupby("类别")["销售额"].agg(["sum", "mean", "count"]) result.columns = ["总销售额", "平均销售额", "订单量"]分组之后还可以结合sort_values排序,把结果按照某个指标从高到低排列,方便快速找出TOP地区或TOP商品:
top5 = result.sort_values("总销售额", ascending=False).head(5)5.2 透视表与多表关联
有些人喜欢用pivot_table做交叉统计。比如想看看“不同区域在不同销售渠道下的销售额”,透视表就是最直观的呈现方式:
pivot = pd.pivot_table( df, values="销售额", index="区域", columns="渠道", aggfunc="sum", fill_value=0 )fill_value=0能让结果表里没有数据的交叉项显示为0,可读性大大提升。pivot_table的aggfunc也支持多个聚合,比如同时设置sum和count,生成各渠道的销售额与订单量矩阵。
多表关联是另一个高频需求。业务数据通常被打散成多张表,比如订单表、商品表、用户表。Pandas的merge相当于SQL里的JOIN。拿订单表和商品表举例,两个表通过商品ID关联:
merged = pd.merge( df_orders, df_products, on="商品ID", how="left" )left参数的意思是订单表为主表,商品信息匹配不到的以NaN填充。这个参数很关键,选错join方式结果会差很多。实际使用中我95%的场景用的是how="left",因为业务上订单表往往是主表,后续分析以它为准。concat函数则用于多张结构相同的表上下拼接,比如一个月一个月的数据文件合并:
df_all = pd.concat([df_jan, df_feb, df_mar], ignore_index=True)6. 数据可视化:让结论自己说话
6.1 用Pandas内置plot快速出图
数据清洗和分析做完,最后一步是可视化。可视化的作用不是让报告好看,而是让人一眼看出数据里的规律。Pandas内置的plot方法基于Matplotlib封装,调用简单,很适合快速探索。
最简单的图形是柱状图,适合观察类别之间的对比:
import matplotlib.pyplot as plt # 解决中文显示问题(后文详述) plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False sales_by_category = df.groupby("类别")["销售额"].sum() sales_by_category.plot(kind="bar", figsize=(10, 6), title="各品类销售额对比") plt.xlabel("品类") plt.ylabel("销售额") plt.xticks(rotation=45) plt.savefig("类别销售柱状图.png", dpi=200, bbox_inches="tight") plt.show()折线图适合看时间趋势,比如按月统计销售额变化趋势:
monthly_sales = df.groupby(df["日期"].dt.to_period("M"))["销售额"].sum() monthly_sales.plot(kind="line", marker="o", figsize=(12, 6)) plt.show()这里用dt.to_period("M")把日期归到月份,是月度趋势分析的标准写法。饼图可以用来展示占比,但超过5个类别时我一般不推荐用饼图,因为人眼对面积的感知远不如对长度的感知准确,柱状图或横向条形图表达起来更清晰。
6.2 用Matplotlib和Seaborn做进阶图表
内置plot方法适合快速探索,但要正儿八经做汇报级图表,我通常切换到Matplotlib和Seaborn。Seaborn的API更简洁,默认配色也好看,一组数据用直方图和箱线图配合看分布,是分析连续变量的标准姿势。
检查销售额分布是否偏态、是否存在离群值,代码可以这样写:
import seaborn as sns fig, axes = plt.subplots(1, 2, figsize=(14, 5)) sns.histplot(df["销售额"], bins=30, kde=True, ax=axes[0]) axes[0].set_title("销售额分布直方图") sns.boxplot(x=df["销售额"], ax=axes[1]) axes[1].set_title("销售额箱线图") plt.tight_layout() plt.show()histplot里加了kde=True,会在直方图上叠加一条核密度曲线,分布形态看得更清楚。箱线图上那些单个圆点,就是按照IQR规则识别出的异常值,和我在4.2节里用代码算出来的基本一致。
散点图适合看两个连续变量之间的关系。比如分析广告投入和销售额是否存在相关关系:
sns.scatterplot(data=df, x="广告投入", y="销售额", hue="区域") plt.show()hue参数按第三维度给点着色,一张图里能表达三个变量,信息密度高了不少。
6.3 中文乱码问题的终极解法
Matplotlib默认字体不支持中文,图表标题、坐标轴标签一旦是中文,就会变成一个个方块。这个问题几乎每个初学者都会遇到,我提供一个可靠的处理方案。在画图代码开头加上下面两条设置:
plt.rcParams["font.sans-serif"] = ["SimHei"] # 也可以用微软雅黑 "Microsoft YaHei" plt.rcParams["axes.unicode_minus"] = False # 解决负号显示为方块的问题SimHei是黑体,大多数系统都有。如果你在Jupyter里设置完仍无效,可能是系统缺字体,需要自行注册字体文件,但这种情况较少,一般设置SimHei或Microsoft YaHei就能解决。这个设置要在绘制任何图像之前执行,否则已经创建的对象不会自动生效。
之前看到有人画图时用Seaborn默认主题,图表里英文字体正常,中文却变成方块,原因就是上面两条没有写。把这两条当成画图前必写配置,能省很多排查时间。
7. 一个完整的实战案例:门店销售数据分析
7.1 案例背景
下面用一份模拟的门店销售订单数据,把从数据清洗到可视化的完整流程串起来。数据包含订单号、日期、门店、区域、商品类别、销售额、数量等字段。实际工作中这份数据可能是从ERP系统导出的Excel,也可能存在数据库里,用pd.read_sql直接读。这里我们假设已经拿到一份Excel文件。
假设的问题是:华东大区的销售额为什么连续三个月下滑?各品类表现如何?哪些门店贡献最大?需要给出判断依据。
7.2 完整代码流程与解读
第一步,读取数据并观察结构。
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False df = pd.read_excel("门店销售数据.xlsx", sheet_name="订单明细", engine="openpyxl") print(df.shape) print(df.dtypes) print(df.head())第二步,数据清洗。先处理缺失值,再转日期格式,接着去重,最后筛选出华东大区的数据。
# 查看缺失情况 print(df.isnull().sum()) # 日期列转成标准时间类型 df["日期"] = pd.to_datetime(df["日期"]) # 销售额列去除千分位逗号并转为数值类型 df["销售额"] = pd.to_numeric(df["销售额"].astype(str).str.replace(",", ""), errors="coerce") # 删除销售额为空的行 df.dropna(subset=["销售额"], inplace=True) # 按订单号去重 df.drop_duplicates(subset=["订单号"], inplace=True) # 筛选华东大区 df_huadong = df[df["区域"] == "华东"]第三步,按门店聚合,找销售额Top和Bottom。
store_sales = df_huadong.groupby("门店")["销售额"].sum().sort_values(ascending=False) print(store_sales.head(10)) print(store_sales.tail(10))第四步,按月统计总销售额,看趋势。
monthly_sales = df_huadong.groupby(df_huadong["日期"].dt.to_period("M"))["销售额"].sum() monthly_sales.plot(kind="line", marker="o", figsize=(12, 6), title="华东大区月度销售额趋势") plt.xlabel("月份") plt.ylabel("销售额") plt.grid(True, linestyle="--", alpha=0.6) plt.savefig("华东月度销售额趋势.png", dpi=200, bbox_inches="tight") plt.show()第五步,按品类透视,看哪些品类在下降。
category_trend = df_huadong.pivot_table( values="销售额", index=df_huadong["日期"].dt.to_period("M"), columns="商品类别", aggfunc="sum", fill_value=0 ) category_trend.plot(kind="bar", figsize=(14, 7), title="华东大区各品类月度销售额") plt.legend(title="品类", bbox_to_anchor=(1.05, 1)) plt.tight_layout() plt.show()第六步,找出异常订单的门店分布。
Q1 = df_huadong["销售额"].quantile(0.25) Q3 = df_huadong["销售额"].quantile(0.75) IQR = Q3 - Q1 upper = Q3 + 1.5 * IQR df_huadong_outlier = df_huadong[df_huadong["销售额"] > upper] print(df_huadong_outlier.groupby("门店")["销售额"].agg(["count", "sum"]))7.3 结果解读与心得
把上面几步跑完,华东大区销售额下滑的原因基本就浮出水面了。如果趋势图显示滑落在某个月突然发生,而品类透视表显示主要是某两个品类在降,那就能把排查范围缩小到“对应品类在核心门店是否缺货、价格调整、竞品挤压”等具体业务原因上。这就是数据分析的价值:不是告诉你销售在降,而是帮你定位到业务可以行动的层级。
这套代码的价值在于可复用。下个月数据导出来,把这些代码重新跑一遍,就能自动生成趋势图、品类矩阵、异常门店清单。只要把读取路径和数据质量检查的部分保留,整套流程会成为你长期使用的模板。
8. 常见问题与排查技巧实录
8.1 Pycharm或Jupyter里找不到Pandas模块
这个问题的根源通常是解释器选错了。PyCharm右下角状态栏会显示当前解释器,点击可以切换。Jupyter里执行!pip install pandas后如果还是报ModuleNotFoundError,大概率是安装命令和当前内核用的Python不一致。建议在Jupyter里这样确认:
import sys print(sys.executable)然后在终端安装时指定这个解释器的pip路径。或者干脆在Jupyter单元格里执行!pip install pandas,这样能保证装到当前内核对应的环境中。
8.2 读取CSV/Excel报编码或语法错误
CSV文件读取报UnicodeDecodeError,多半是编码参数没设对。国内Excel另存的CSV,用encoding="gbk"或encoding="gb18030"基本能解决;不行还可以用第三方库chardet检测文件真实编码。Excel文件读取报Missing optional dependency 'openpyxl',就是用pip install openpyxl补装依赖。
8.3 SettingWithCopyWarning警告怎么处理
Pandas的链式赋值是新手最容易踩的坑,比如df[df["销售额"] > 100]["是否达标"] = "是",执行后原始df没被修改,还弹出一堆警告。推荐做法是:先筛选出子DataFrame后用.loc修改,或者直接使用.copy()生成副本再操作,彻底避免这个警告:
df_sub = df[df["销售额"] > 100].copy() df_sub.loc[:, "是否达标"] = "是"我在实战项目中,凡是会对切片结果做修改的,都习惯先.copy(),既避开了警告,也防止后续步骤污染原数据。
8.4 groupby后列名层级不清
groupby传多个聚合函数后生成的多级列名,容易在后续代码里引用出错。建议第一时间用columns属性展平列名,或手动设置:
result = df.groupby("区域")["销售额"].agg(["sum", "mean"]) result.columns = ["总销售额", "平均销售额"]8.5 str处理时NaN报错
对含有缺失值的列做字符串操作,比如df["备注"].str.contains("退款"),会直接返回NaN而不是False,逻辑判断时极易出错。可以先用fillna("")把缺失值填充成空字符串,再统一处理。
8.6 代码跑得很慢怎么办
Pandas跑大数据集慢,主要原因往往是用标量循环代替了向量化操作。举个例子,要按某个条件生成新列,新手可能会用for循环逐行判断,几十万行跑起来极慢。正确做法是用np.where或loc批量赋值:
import numpy as np df["是否高价值"] = np.where(df["销售额"] > 5000, "高价值", "普通")另一个优化技巧是如果只需要部分列,读取时就指定usecols参数,能显著减少内存占用和读取时间。处理上亿级数据时还得用分块读取或换用Polars,那是另一个话题了,但当数据量还在百万行级别时,Pandas的正确用法足够解决问题。
个人实操中的一点体会
做了这么多年数据相关的工作,我最大的感受是:数据分析的瓶颈从来不是工具,而是对业务的理解和清洗数据的耐心。Pandas能帮你高效地完成80%的工作,但能否拿到准确结论,取决于你有没有在一开始想清楚“为什么要分析这份数据、哪些字段是关键的、哪些脏数据会影响结论”。那些看起来枯燥的清洗步骤,往往决定了一张数据报表和一张废纸的区别。希望这篇的经验和方法,能让你拿到数据后不再手足无措,能按自己的节奏把一条清晰的分析路径走完。