3. 数据采集与理解
数据是构建分群评分沙盘的基石。在开始任何模型训练之前,必须明确数据的来源、掌握加载方法,并快速对数据质量形成第一印象。本章将围绕“数据从哪里来”、“如何加载到Python”、“数据长什么样”三个核心问题展开。
3.1 数据来源:CSV、数据库与API
在实际项目中,数据通常以三种形态存在。理解每种来源的接入方式,是数据采集的第一步。
| 来源类型 | 典型场景 | 接入方式 | 注意事项 |
|---|---|---|---|
| CSV文件 | 离线报表、历史数据导出 | pd.read_csv() |
编码(UTF-8/GBK)、分隔符、缺失值标记 |
| 数据库 | 业务系统(MySQL/PostgreSQL) | pd.read_sql() + SQLAlchemy |
连接池管理、SQL注入防范、分页查询 |
| API接口 | 实时数据、第三方服务 | requests.get() + JSON解析 |
认证Token、限流策略、异常重试 |
实战建议:在沙盘构建初期,优先使用CSV文件进行快速原型验证。待模型稳定后,再切换至数据库或API实现自动化流水线。
3.2 数据加载:pd.read_csv 核心参数
pd.read_csv() 是Python数据分析中使用频率最高的函数之一。掌握其关键参数,可以避免90%的加载错误。
import pandas as pd
# 标准加载方式
df = pd.read_csv(
'customer_scores.csv', # 文件路径
sep=',', # 分隔符,默认逗号
encoding='utf-8', # 编码,中文数据常用 'gbk'
header=0, # 表头行索引,0表示第一行
index_col=None, # 指定某列为行索引
usecols=['user_id', 'age', 'score'], # 只读取指定列
dtype={'user_id': str}, # 强制指定列类型
na_values=['', 'NULL', 'NA'], # 将特定值视为缺失值
nrows=1000 # 仅读取前1000行用于快速预览
)
print(f'数据加载完成,共 {df.shape[0]} 行,{df.shape[1]} 列')
常见踩坑:CSV文件中的数字列如果包含逗号(如 "1,234"),会被读成字符串。建议在加载前用
thousands=',' 参数处理,或加载后使用 pd.to_numeric() 转换。
3.3 数据概览:三剑客 head()、info()、describe()
数据加载完成后,不要急于建模。先用三个方法快速建立对数据的全局认知。
3.3.1 head() — 看样貌
默认显示前5行,用于检查列名是否对齐、数据格式是否正常、是否有明显的异常值。
df.head(10) # 查看前10行
3.3.2 info() — 看结构
显示每列的非空计数、数据类型和内存占用。这是判断数据完整性和类型正确性的第一道关卡。
df.info()
# 输出示例:
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 5000 entries, 0 to 4999
# Data columns (total 8 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 user_id 5000 non-null object
# 1 age 4985 non-null float64
# 2 income 4950 non-null float64
# 3 score 5000 non-null int64
# dtypes: float64(2), int64(1), object(1)
# memory usage: 312.5 KB
3.3.3 describe() — 看分布
对数值型列自动计算均值、标准差、四分位数等统计量。对分类型列使用 include='object' 查看频次。
df.describe() # 数值列统计
df.describe(include=['object']) # 文本列统计
关键检查点:如果
info() 显示某列 Dtype 为 object 但实际应为数值,或者 describe() 中 count 远小于总行数,说明存在缺失值或类型错误,必须在数据清洗阶段处理。
3.4 实战:快速数据质量检查清单
每次加载新数据后,建议按以下清单执行例行检查,形成肌肉记忆。
- 维度确认:
df.shape— 行数和列数是否符合预期。 - 列名检查:
df.columns.tolist()— 是否有空格、大小写不一致、中文乱码。 - 缺失值扫描:
df.isnull().sum()— 哪些列有缺失,缺失比例是否可接受。 - 唯一值检查:
df['user_id'].nunique()— 主键是否唯一,是否存在重复记录。 - 数值范围:
df['age'].min()/max()— 是否有超出业务逻辑的异常值(如年龄200岁)。