简介:面向数据分析初学者和Python使用者,这份Word文档系统讲解如何借助Python生态完成数据分析,覆盖数值计算库NumPy、表格处理库Pandas、可视化库Matplotlib以及探索性数据分析(EDA),并从数据分析的六个步骤——明确需求、收集数据、清洗加工、分析、共享与报告——展开,帮助读者建立从业务问题到数据结论的完整流程意识。资源以Word格式提供,压缩包内共1个文件,大小约2.05MB,轻量易读,便于离线查看或打印;目前已有46人学习下载,适合刚接触数据分析、希望快速搭建知识框架的读者。内容上,文档先介绍数据分析的整体概念和流程,再深入演示NumPy数组的创建,比如使用empty函数生成未初始化数组、zeros函数生成全零数组,并通过加法、减法、乘法、除法示例说明直接运算与NumPy函数两种做法的异同,同时讲解索引与切片的基本规则。这些知识点结合Pandas表格处理、Matplotlib图表绘制和EDA常见思路,能够帮助读者理解数据在Python中的存储、变换与呈现方式,既适合自学入门,也可作为课程讲义的辅助资料。
1. Python 数据分析的主线:从原始数据到决策依据
一提到“用 Python 做数据分析”,很多人第一反应是 notebook 里画几根折线图。实际上数据分析是一条从原始数据到决策动作的完整链路:把散落在 Excel、数据库、接口、日志里的数据收进来,转换成口径统一的干净结构,再组织成能聚合、能对比、能建模的形态,最后变成一句业务能直接执行的话,比如“下季度华南区备货提高 20%”。这里的收集、转换、组织不是论文里的修辞,而是 pandas 里三个彼此独立又环环相扣的阶段。这篇文章面向的是数据分析师、转岗接触数据的业务同学,以及准备接分析任务的研发。希望读完能照着步骤理出自己的分析流程。
2. 数据收集:把第一份数据读进 DataFrame 的常用路线
“收集”这一步没有统一答案,但有一个统一出口:让所有来源的数据都进入 pandas DataFrame。文件、数据库、API、抓取来的网页数据甚至 pcap 流量日志,最后都转成“行是样本、列是字段”的表结构,后续转换和分析才能用同一套工具。下面按最常见的数据来源,给三条高复用路线。
2.1 先把运行环境立住:python 安装与编辑器配置
做数据分析不推荐把包装到全局环境。我一般的做法是:安装官方 python 解释器后,在项目目录里建虚拟环境,再安装依赖。这样做的好处是,换机器或者同时做多个数据分析项目时,不会出现“这个包装了但另一个项目跑不起来”的依赖冲突。
python3 -m venv .venv source .venv/bin/activate # Windows PowerShell 下激活命令是 .venv\Scripts\activate pip install pandas numpy matplotlib seaborn scikit-learn requests openpyxl这段命令会创建名为.venv的隔离环境并安装完整的数据分析基础包。pandas 负责表格处理,numpy 提供数值运算,matplotlib 和 seaborn 做可视化,scikit-learn 用于建模预测,requests 拉取接口数据,openpyxl 让 pandas 能读写 Excel。
编辑器方面,vscode 里装好 Python 扩展后,需要手动选中虚拟环境:按Ctrl+Shift+P打开命令面板,输入Python: Select Interpreter,选择.venv路径下的解释器。这一步经常被忽略,导致代码能写但不能运行。pycharm 用户则是在 Settings 里把 Project Interpreter 指向同一个虚拟环境。环境配置不复杂,但 90% 的“安装后 import 报错”都发生在这个环节,值得花十分钟一次配好。
2.2 读取第一批文件:read_csv 的三个关键参数
拿到一份 CSV 后直接pd.read_csv("文件名")虽然能跑,但遇到中文列名、日期字符串、数字被识别成文本等场景就会翻车。我一般会先按下面这样读文件,把格式问题在路上解决,而不是等到清洗阶段再补救。
import pandas as pd df = pd.read_csv( "order_details.csv", encoding="utf-8", # 避免中文乱码 parse_dates=["order_date"], # 提前把日期列解析成 datetime dtype={"store_id": "str"}, # store_id 是编号,不是数值,禁止参与计算 )encoding参数在 Excel 导出的 CSV 里尤其重要,常见的中文编码有utf-8、utf-8-sig和gbk,乱码时优先在这两者之间切换。parse_dates接收一个列名列表,把日期文本转成 pandas 的 datetime 类型,转换之后才能按月份、季度直接聚合。dtype用来指定列的类型,像门店编号、订单号这类看起来是数字、实际没有数值意义的字段,必须声明成字符串,否则后续sum、mean这类函数会误伤它们。
如果文件来自 Excel,读取方式换成pd.read_excel("销售明细.xlsx", sheet_name="订单", engine="openpyxl"),其中sheet_name可以传工作表名称或索引。到这里,一大部分“文件型数据收集”就完成了。
2.3 用 requests 拉 API 数据并转成结构化表格
多数系统的数据不直接给你文件,而是通过 HTTP 接口暴露。比如电商订单、物流轨迹、用户行为事件,都需要先请求接口再转成 DataFrame。这个环节的固定动作是:带超时请求,校验状态码,把 JSON 拍平成表格。
import requests import pandas as pd resp = requests.get( "https://api.example.com/orders", params={"start_date": "2024-01-01", "page_size": 1000}, timeout=10, ) resp.raise_for_status() # 状态码不是 2xx 时直接抛异常,避免把错误响应当数据 data = resp.json() if isinstance(data, list): df = pd.DataFrame(data) else: # 接口返回嵌套 JSON 时,用归一化函数展开嵌套字段 df = pd.json_normalize(data, sep="_")timeout=10让请求在 10 秒内得不到响应就中止,避免爬虫或批处理任务卡死。raise_for_status()是防御性编程的习惯,保证拿到的数据确实是成功的响应。接口返回 JSON 有两种常见结构:顶层是对象数组,直接用pd.DataFrame即可;顶层是单个对象且里面有嵌套列表,比如{"items": [...], "total": 100},就需要pd.json_normalize把嵌套字段展开成多列。爬虫抓回来的 HTML 数据也可以用类似思路,先用解析库提取字段,再交给 pandas,核心流程没有变化。
| 数据来源 | 常用收集方式 | 最常踩的坑 |
|---|---|---|
| CSV / Excel | pd.read_csv / pd.read_excel | 编码不对导致中文乱码 |
| 关系型数据库 | pandas.read_sql 或 客户端导出 CSV | 大表一次性读取内存不足 |
| HTTP API | requests + resp.json() | 忘记设置 timeout,任务挂起 |
| 网络抓包日志 | 解析成 CSV 后走 pandas 路线 | 字段类型需要手动指定 |
这里顺带说一句:做 pcap 流量数据分析时,不要直接用 pandas 读原始抓包文件,先用 pyshark 或 tshark 把需要的字段导出成 CSV 或 JSON,再走上面的读取流程。文件格式千差万别,最终都要收敛到“一张干净的表”,这就是收集阶段的意义。
3. 数据转换:把数据洗到能放心计算的程度
数据收集完,最常见的现状是:空值、重复行、类型错乱、日期格式不统一。转换阶段的目标不是把数据变成“没有错误”,而是把它变成“计算口径明确”的结构。脏数据清洗没有一步到位的银弹,但有一套固定体检流程和几个高频函数可以覆盖八成场景。
3.1 拿到数据先体检:info、isna、nunique 三件套
拿到一张新表,先不要急着head()看前几行,用三个方法做一次系统体检:
print(df.info()) # 列名、非空数量、每列 dtype print(df.isna().sum()) # 每列缺失值数量 print(df.nunique()) # 每列不同值个数,辅助发现维度是否异常info()能快速看出哪些列有缺失,以及类型是否和业务预期一致,比如“价格”列显示为 object 类型,就说明里面有非数字内容。isna().sum()直接给出缺失量,这一步决定后面用删除还是填充。nunique()统计每个字段的去重数量,适合检查“省份”这类维度列是否混入了脏值,比如出现 35 个省而不是 34 个。
3.2 缺失值处理的取舍:dropna 与 fillna 的适用边界
缺失值处理最常见的误区是“一律删掉”和“一律填 0”。这两种做法都有代价:删行会损失样本量,填 0 则会拉低均值、放大波动。我一般先看字段的业务含义,再决定策略。关键标识字段缺失直接删行,连续数值字段缺失用统计值填充,类别字段缺失用独立标记。
df_clean = df.dropna(subset=["order_id"]) # 订单号缺失的行删掉,无法恢复业务含义 df_clean["amount"] = df_clean["amount"].fillna(0) # 支付金额缺失填 0,表示未支付 df_clean["province"] = df_clean["province"].fillna("未知") # 省份缺失用占位值dropna的subset参数控制了“哪一列出现缺失才删除行”,比全表dropna温和得多。fillna具体填什么要看场景:金额为 0 有业务意义,“这笔订单确实没付钱”;用户性别填“未知”是为了保留样本;而销量这类指标如果缺失,我通常填中位数而不是均值,因为中位数对极端值不敏感。充分理解了字段含义再决定缺失策略,数据才是可解释的。
3.3 类型规范化与特征衍生:astype、to_numeric、cut 的组合
清洗的另一个大头是类型统一。比如金额列可能是"1,234.5"这种带千分位逗号的字符串,日期可能有2024/01/01和2024-01-01两种格式。把这些字段统一成规范类型,是为后续聚合和建模打基础。
df_clean["price"] = pd.to_numeric(df_clean["price"].str.replace(",", ""), errors="coerce") df_clean["order_date"] = pd.to_datetime(df_clean["order_date"], format="%Y-%m-%d", errors="coerce") df_clean["price_tier"] = pd.cut( df_clean["price"], bins=[0, 50, 200, 10000], labels=["低价", "中价", "高价"], )pd.to_numeric的errors="coerce"会把无法解析的字符串转成 NaN,比直接报错更适合脏数据场景。pd.to_datetime的format参数显式声明日期格式,解析速度比自动推断快,同时避免歧义。pd.cut做的事情是把连续价格离散化成“低/中/高”三个档位,这种从原始字段衍生新字段的操作叫特征工程,是数据分析里最出活的部分。
3.4 用 pipe 串一个可复用的清洗流程
实际情况里清洗步骤不止三步。如果每次都在全局变量上改改,脚本会变成一团乱麻。我会把转换逻辑封装成独立函数,再用pipe串成链式调用。这样每个环节单独可测,也方便在多个数据集上复用同一套管线的清洗逻辑。
def remove_duplicate_orders(df: pd.DataFrame) -> pd.DataFrame: return df.drop_duplicates(subset=["order_no"], keep="first") def fill_missing(df: pd.DataFrame) -> pd.DataFrame: df = df.copy() df["amount"] = df["amount"].fillna(0) return df df_final = ( df.pipe(remove_duplicate_orders) .pipe(fill_missing) .pipe(parse_datetime) )用pipe的好处是每个函数只接收 DataFrame、返回 DataFrame,函数内部做了copy()避免修改原始数据。这样一步步往下传,每一步的输入输出都清晰可见。需要注意的是函数内部如果没有df = df.copy(),pandas 有触发SettingWithCopyWarning的风险,我一般会显式复制,宁可多一份内存也不要出现警告和潜在的逻辑问题。
关于重复值,drop_duplicates(subset=["order_no"])处理的是“同一订单出现多次”的问题,subset指定判断重复依据的字段,keep="first"保留第一次出现的行。按照去重、填充、类型转换这个顺序组织清洗流程,逻辑表达自然,也很少出 bug。
4. 数据组织与分析:分组、透视后才能形成判断
清洗之后的数据还是“明细表”,要把它变成能看懂的分析结果,就需要组织这一步。组织的方式离不开两个维度:按什么维度看、用什么指标衡量。Excel 里的数据透视表和 SUMIF,在 pandas 里对应groupby和pivot_table,这是把明细变成观点的核心操作。
4.1 用 groupby 完成按时间维度的聚合
分析需求里最常见的句式是“按月份看销售额”“按城市看订单量”。这类需求在 pandas 里用groupby配合agg一次完成,不需要写循环。
monthly = ( df_final.groupby(pd.Grouper(key="order_date", freq="ME")) .agg( order_count=("order_id", "count"), revenue=("amount", "sum"), avg_price=("amount", "mean"), ) .reset_index() )pd.Grouper(key="order_date", freq="ME")表示把日期字段按月分组,freq="ME"是“月结束”的缩写,注意 pandas 2.2 之后用"M"会出现弃用警告,直接写"ME"更规范。agg里用“新列名 = (原列, 聚合函数)”的语法同时计算多组指标,订单数、总金额、平均金额一次拿到。reset_index()把分组键恢复为普通列,便于后续和同类数据合并。
4.2 用 pivot_table 做交叉维度汇总
groupby处理的是单维度拆解,业务上更常见的还有“时间 × 品类”“省份 × 渠道”这种交叉需求,pivot_table是更直观的解法。
pivot = df_final.pivot_table( index="province", columns="price_tier", values="amount", aggfunc="sum", fill_value=0, )换成业务语言来描述这段代码的命令逻辑:以省份作为行索引,价格档位作为列名,表格里每个格子放的是该省份在该价格档位上的总销售额;fill_value=0让没有数据的格子显示 0,避免出现 NaN 影响后续计算。透视之后得到的是一个行列结构清晰的表格,可以直接输出到 Excel,或者喂给可视化工具。
4.3 描述统计与相关性:从表格变成结论
聚合和透视让我们看到趋势,但一个数值“高不高”很难靠肉眼判断,需要统计指标来支撑判断。describe()一次性给出均值、标准差、四分位数;corr()则计算数值列之间的相关系数,其中method="spearman"适用于非线性单调关系。
print(df_final[["amount", "quantity", "cost"]].describe()) corr = df_final[["amount", "quantity", "cost"]].corr(method="spearman") print(corr)一个容易踩的误区是:相关系数高不代表因果。金额和成本高度相关,是因为成本本身参与金额构成,这是业务上必然的结果,而不是发现了一个“新结论”。另一个分析误区是拿总量数据直接做对比,忽略分母和背景。比如两个门店销售额相同,但门店 A 面积是 B 的三倍,坪效完全不同。真正能推动决策的洞察,来自“拆分维度和选择指标”这两个动作,而不是相关系数数值本身。
4.4 可视化只保留三种类型:趋势、分布、对比
数据分析里的可视化不是画得越炫越好,图表的作用是压缩信息。日常汇报我会固定用三张图:折线图看时间趋势,箱线图看分布,柱状图做对比。代码固定在同一个模板里,后续换数据只改字段名。
import matplotlib.pyplot as plt import seaborn as sns sns.set_theme(style="whitegrid") fig, ax = plt.subplots(figsize=(8, 4)) sns.lineplot(data=monthly, x="order_date", y="revenue", marker="o", ax=ax) ax.set_title("月度收入趋势") ax.set_xlabel("月份") ax.set_ylabel("销售额") plt.tight_layout() plt.savefig("monthly_revenue.png", dpi=150) plt.show()| 分析需求 | 推荐图表 | 对应 seaborn 函数 |
|---|---|---|
| 时间趋势 | 折线图 | sns.lineplot |
| 数据分布和离群点 | 箱线图 | sns.boxplot |
| 分类对比 | 柱状图 | sns.barplot |
marker="o"让每个数据点显示圆点,便于读取具体数值。dpi=150保证保存的图片放大后不模糊。如果分析的是单细胞测序表达量或医疗健康数据,关心的是分布和组间差异,同样用这三张图就能覆盖大部分展示需求;可视化工具的复杂度不该超过数据本身的复杂度。
5. 未来预测与决策落地:最小回归模型与验证技巧
数据分析的最后一公里是“未来预测”。一个能支撑决策的预测模型不必一开始就上神经网络,线性回归在解释性和稳定性上是很好的起点。我们拿第 4 章生成的monthly数据,用 sklearn 拟合一个最小模型,并验证预测可信度。
import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error X = np.arange(len(monthly)).reshape(-1, 1) # 用时间序号作为特征 y = monthly["revenue"].values # 月度销售额作为目标 model = LinearRegression().fit(X, y) # 用最后 3 个月做简单回测 mae = mean_absolute_error(y[-3:], model.predict(X[-3:])) print(f"MAE: {mae:.2f}, 月度平均增量: {model.coef_[0]:.2f}")这里把时间建模成线性序号,coef_的含义是“每月平均销售额增量”。mean_absolute_error给出最近三个月的平均预测偏差,如果偏差在可接受范围内,这个增量就能用于预算制定。要注意的是,这个模型只在趋势稳定时有效,遇到季节波动、促销活动或突发事件,线性假设会被破坏,需要引入更多的特征列。预测结果落地成决策前,还要做一次业务合理性检查。
| 验证动作 | 操作方式 | 审查重点 |
|---|---|---|
| 数据完整性 | 检查清洗前后行数和关键字段缺失率 | 数据是否覆盖完整业务周期 |
| 口径一致性 | 和业务方确认指标定义 | 销售额是含税还是不含税 |
| 模型回测 | 时间序列必须用前段训练、后段验证 | 避免随机切分导致数据泄漏 |
| 边界外推 | 看模型在极端区间的表现 | 会不会预测出负销售额 |
最后说一个关于“预测结果落地”的技巧:模型给出的每个数值,都要转成业务动作,否则就只是数字。比如回测显示月均增量是 2 万元,下一步应该追问:这个增量来自新客还是老客、来自哪个区域、要不要调整城市月度目标。分析报告里写“预计下月销售额增长 2 万”不够,要能落到“采购量上调 5%”这种可执行的结论上。数据分析的终点是决策,模型是为决策降低不确定性的工具。
本文还有配套的精品资源,点击获取