2. 数据接入与探索性分析

特征工程的质量,很大程度上取决于我们对原始数据的理解深度。在 Databricks 平台上,数据可能来自 DBFS 文件、Delta Lake 表、外部 JDBC 数据库或云对象存储(如 S3、ADLS、GCS)。本节的目标不是立刻开始构造特征,而是先把这些异构数据源统一接入 Spark,完成数据概览、缺失值分析、分布统计与可视化,最终形成一份"可信、可解释、可追溯"的原始数据集,为后续特征工程提供稳定输入。

一、四类数据源的接入方式与选择依据

Databricks 的读取能力可以概括为"统一入口、按源适配"。无论数据来自哪里,最终都通过 Spark DataFrame 或 Spark SQL 表的形式参与后续分析。

  • DBFS 文件:适合 CSV、Parquet、JSON 等落地文件。使用 spark.read.format("parquet").load("/FileStore/raw/orders/") 即可读取;若为 CSV,需显式指定 header、inferSchema 或自定义 schema,避免类型推断带来的隐性错误。
  • Delta Lake 表:生产环境首选。Delta 自带事务日志、Schema 演进与时间旅行能力,读取时可直接 spark.read.table("silver.user_profile"),也可用 versionAsOf 回溯历史版本,便于排查数据异常。
  • JDBC 数据源:对接 MySQL、PostgreSQL、SQL Server 等业务库。关键参数包括 url、dbtable、user、password、numPartitions、partitionColumn、lowerBound、upperBound。合理设置分区列可让并行读取真正生效,否则会退化为单分区全表扫描。
  • 云存储:通过 s3a://、abfss://、gs:// 等协议访问。需要提前在集群或 Notebook 中挂载凭证,或使用 Unity Catalog 的 External Location 统一管理权限。

选择依据可以简单归纳为:结构化且需事务保障选 Delta;外部业务库选 JDBC;批量文件选 DBFS 或云存储;跨云共享选云存储 + 外部表。接入阶段就要记录数据来源、读取时间、Schema 版本,这些元信息在后续特征回溯时非常关键。

二、数据概览:先看清"有什么"

接入后第一步是概览。常用手段包括 df.printSchema() 查看字段与类型、df.count() 获取行数、df.show(5) 抽样观察、df.describe().show() 得到数值列的 count/mean/stddev/min/max。对于宽表,建议用 Spark SQL 一次性输出字段清单:

SELECT column_name, data_type
FROM system.information_schema.columns
WHERE table_name = 'raw_orders';

概览阶段要重点关注三类信号:字段类型是否符合预期(如金额被读成 string)、主键/时间字段是否存在空值、分区字段是否与业务日期一致。这些信号会直接影响后续特征构造的可行性。

三、缺失值分析:从"有多少"到"为什么"

缺失值分析不能只统计比例,还要区分缺失模式。常用做法是对每个字段计算缺失率,并按缺失率排序:

from pyspark.sql import functions as F
missing = df.select([
    (F.count(F.when(F.col(c).isNull(), c)) / F.count("*")).alias(c)
    for c in df.columns
])
missing.show()

如果某字段缺失率超过 60%,通常需要与业务确认是否保留;若缺失集中在特定时间段或特定渠道,则可能是采集链路问题而非随机缺失。对于关键特征字段,建议同时输出"缺失 + 异常"联合视图,例如金额为负、年龄超过 120、时间戳早于系统上线日期等,这些都会在特征工程阶段被放大。

四、分布统计与可视化:判断特征是否可用

分布统计的目标是判断特征是否偏态、是否存在极端值、类别是否极度不平衡。数值列可计算分位数(如 P1、P25、P50、P75、P99),类别列可统计 Top-N 频次。Databricks Notebook 内置 display() 可直接渲染直方图、箱线图与散点图,无需额外引入可视化库。

例如对用户年龄做分桶统计:

display(df.groupBy(F.floor(F.col("age") / 10) * 10).count().orderBy("floor(age / 10) * 10"))

观察结果时,若某类别占比超过 95%,独热编码后会产生大量稀疏列,此时应考虑目标编码或频次编码;若数值列呈长尾分布,后续标准化前可能需要先做对数变换。可视化不是装饰,而是为特征变换决策提供依据。

多源数据接入与探索性分析链路 从四类数据源到特征工程可用的原始数据集 DBFS 文件 CSV / Parquet / JSON Delta Lake 表 事务日志 / 时间旅行 JDBC 数据源 MySQL / PostgreSQL 云对象存储 S3 / ADLS / GCS Spark DataFrame / Spark SQL 统一接入 Schema 校验 · 分区并行读取 · 凭证与权限管理 ① 数据概览 • printSchema / count • describe 统计量 • 字段类型与主键检查 • 分区字段一致性 ② 缺失值分析 • 各字段缺失率排序 • 缺失模式(时间/渠道) • 缺失 + 异常联合视图 • 关键字段保留决策 ③ 分布统计与可视化 • 分位数 P1 / P50 / P99 • 类别 Top-N 频次 • 直方图 / 箱线图 • 偏态与不平衡判断 输出:可信、可解释、可追溯的原始数据集 供特征工程阶段直接消费

五、形成原始数据集:落盘与元信息记录

探索完成后,建议将清洗后的原始数据以 Delta 格式写入特征工程的输入区,例如 /mnt/feature/raw/orders_v1。写入时保留原始字段,不做业务变换,只做必要的类型修正与去重。同时记录一份元信息表,包含数据源、读取时间、行数、字段数、缺失率摘要、Schema 版本。这样在后续特征回溯或模型复现时,可以快速定位输入数据的来源与状态。

探索性分析阶段不要急于删除"看起来没用"的字段。很多在单表分析中不显著的字段,在与其他表关联后可能成为关键特征。保留原始字段、记录分析结论,是更稳妥的做法。
JDBC 读取时若未设置 partitionColumn 与上下界,Spark 会使用单分区读取,大表可能耗时数小时。务必先用 EXPLAIN 或 Spark UI 确认并行度。

完成本节后,我们得到的不只是一份数据,更是一份对数据"脾气"的理解:哪些字段可靠、哪些字段需要谨慎处理、哪些分布会影响后续编码与变换。这些判断将直接决定特征工程阶段的技术选型与验证策略。