3、数据准备与清洗:数据来源、采集方法与质量治理

旅游需求预测模型的精度,往往不取决于算法多么先进,而取决于输入数据的质量与结构。真实业务场景中的数据分散在预订系统、搜索引擎、气象服务、票务平台等多个异构源中,存在缺失、异常、时区不一致、粒度不统一等问题。本章围绕数据来源、采集方法、缺失值处理、异常值检测、时间对齐与重采样五个核心环节,构建一套可落地的数据工程链路,为后续特征工程与模型训练奠定坚实基础。

旅游需求预测数据工程链路 数据源层 历史预订记录 搜索指数/舆情 天气/节假日 经济指标/汇率 竞品/航班运力 采集层 API接口/数据库同步 爬虫/日志采集 第三方数据服务 手工录入/文件导入 流式/批式管道 清洗与对齐层 缺失值处理 异常值检测 时间对齐/时区统一 重采样(日/周/月) 去重/一致性校验 建模数据集 特征矩阵 目标变量序列 时间索引 数据版本记录 质量报告 质量反馈与迭代优化 关键工程要点: ① 数据源优先级:内部交易数据 > 外部行为数据 > 宏观环境数据 ② 时间对齐基准:统一使用 UTC 存储,展示时按目标时区转换 ③ 重采样策略:预测粒度决定重采样周期,日粒度预测需避免星期效应混淆 ④ 质量门槛:缺失率 >30% 的特征建议剔除,异常值占比 >5% 需排查数据源

3.1 数据来源:多源异构数据的价值分层

旅游需求预测的数据来源可划分为三个层级:核心交易层(历史预订、订单取消、入住/出票记录)、行为意图层(搜索指数、页面浏览、收藏加购、社交媒体舆情)、环境驱动层(天气、节假日、经济指标、重大事件、航班运力)。三个层级对预测模型的贡献不同:交易层提供需求基准,行为层提供短期波动信号,环境层提供结构性变化解释。

数据类别 典型字段 采集频率 预测价值 主要挑战
历史预订 订单号、入住日期、预订日期、渠道、房型、价格、取消标记 实时/每日 核心需求基准 取消率波动、提前预订天数分布
搜索指数 关键词、设备类型、地域、时间戳 小时级 短期需求先导指标 噪声大、关键词覆盖不全
天气数据 温度、降水、风速、空气质量、预警 小时级 影响当日/次日需求 预报与实况差异、空间粒度
节假日 日期、类型、调休安排、连休天数 年度 结构性峰值 调休政策变化、地域差异
经济指标 GDP、CPI、消费者信心指数、汇率 月度/季度 中长期趋势 发布滞后、与旅游需求传导路径长
经验提醒:搜索指数与预订量之间存在 7-21 天的领先相关关系,但领先天数随目的地类型变化。城市休闲游领先 3-7 天,自然景区游领先 7-14 天,出境长线游领先 21-45 天。在特征工程中应针对不同产品线设置不同的滞后窗口。

3.2 数据采集方法:管道设计与工程实现

数据采集的核心矛盾是时效性与系统稳定性之间的平衡。对于预订数据,推荐使用增量同步方式,每日凌晨拉取前一日全量变更;对于搜索指数,采用小时级定时任务调用第三方API;对于天气数据,使用预报数据而非实况数据,因为预测时只能获取预报值。

# 伪代码:预订数据增量采集管道
def fetch_booking_data(last_sync_time):
    # 1. 从业务库读取增量变更
    changes = db.query("""
        SELECT * FROM booking_orders 
        WHERE updated_at > %(last_sync_time)s
    """, {"last_sync_time": last_sync_time})
    
    # 2. 写入数据湖临时区
    staging_path = f"s3://data-lake/staging/booking/{date.today()}"
    write_parquet(changes, staging_path)
    
    # 3. 执行数据质量检查
    quality_report = run_quality_checks(staging_path)
    
    # 4. 原子性写入正式分区
    if quality_report.pass_rate > 0.95:
        move_to_formal_partition(staging_path)
        update_sync_checkpoint(datetime.now())
    else:
        alert_engineer("数据质量未达标", quality_report)

采集方法对比

方法 适用场景 时效性 成本 风险
API 直连 内部系统、有官方接口的第三方 实时/准实时 低 接口限流、字段变更
数据库同步 业务库到数仓 T+1 低 主库性能影响
爬虫采集 无官方接口的公开数据 小时级 中 反爬、法律风险
日志采集 用户行为数据 准实时 中 数据量大、清洗复杂
手工导入 线下渠道、合作伙伴数据 不定期 高 格式不统一、易出错

3.3 缺失值处理:从删除到插补的决策框架

缺失值处理不能一刀切。首先需要判断缺失机制:完全随机缺失(MCAR)、随机缺失(MAR)、非随机缺失(MNAR)。在旅游场景中,天气数据缺失往往与设备故障有关(MCAR),而高端酒店预订数据缺失可能与渠道覆盖不足有关(MNAR),后者需要业务侧介入。

处理策略选择

  1. 删除策略:当缺失率 <5% 且为 MCAR 时,可直接删除缺失样本;当某特征缺失率 >30% 时,建议剔除该特征。
  2. 统计插补:均值/中位数/众数插补适用于数值型低缺失率场景,但会降低方差,导致预测区间偏窄。
  3. 时间序列插补:线性插值、样条插值适用于连续时间序列;前向填充(ffill)适用于预订量这类具有强自相关的数据。
  4. 模型插补:使用 KNN、随机森林等模型基于其他特征预测缺失值,适用于特征间相关性较强的场景。
  5. 业务规则插补:节假日数据缺失时,可根据国务院放假安排手工维护;天气数据缺失时,可回退到气候平均值。
实战建议:对于预订数据中的取消标记缺失,不要简单填充为"未取消"。应结合渠道特征判断:OTA渠道的取消率通常高于官网直销,若某渠道取消标记缺失率超过 20%,建议单独建模预测取消概率,而非直接填充。

3.4 异常值检测:区分真实波动与数据错误

旅游需求数据天然具有高波动性,节假日峰值可能是正常值的 3-5 倍。因此,异常值检测必须结合业务日历和历史同期进行判断,不能仅依赖统计阈值。

三层检测法

层级 方法 适用场景 示例
全局统计 Z-score、IQR 平稳序列的初步筛查 某日预订量超过均值+3σ
局部窗口 移动平均残差、STL分解 识别趋势中的突变点 连续7天平稳后突然下降50%
业务规则 日历事件、竞品动态 判断异常是否合理 演唱会/赛事/极端天气导致的激增
风险提示:不要轻易删除"看起来异常"的数据点。例如,某景区因举办音乐节导致当日预订量暴增 300%,这属于真实需求信号,应保留并标记事件标签。只有确认是数据录入错误(如订单金额为负数、日期格式错误)时才应删除或修正。

3.5 时间对齐与重采样:构建统一的时间索引

多源数据的时间粒度天然不一致:预订数据精确到秒,搜索指数为小时级,天气数据为3小时预报,经济指标为月度。建模前必须将所有数据对齐到统一的时间索引上。

对齐与重采样操作流程

  1. 统一时区:所有时间戳转换为 UTC 存储,展示时按目标市场时区转换。中国区业务建议使用 Asia/Shanghai。
  2. 确定基准粒度:根据预测目标决定。日粒度预测是最常见的选择,周粒度适合长线产品,小时粒度适合景区门票预约。
  3. 重采样规则:预订量使用求和(sum),价格使用均值(mean),天气使用最大值/最频繁值,节假日使用布尔标记。
  4. 滞后特征构造:对齐后,为搜索指数构造 7/14/21 天滞后特征,为天气构造当日/前一日特征。
  5. 验证对齐结果:检查重采样后是否存在空窗期,尤其是跨月、跨年边界。
import pandas as pd

# 对齐示例:将小时级搜索指数重采样为日粒度
search_daily = search_hourly.resample('D', label='right', closed='right').agg({
    'search_volume': 'sum',
    'device_type': lambda x: x.mode()[0] if not x.empty else 'unknown'
})

# 合并预订数据与搜索数据
merged = booking_daily.join(search_daily, how='left', lsuffix='_booking', rsuffix='_search')

# 检查对齐后的缺失情况
missing_report = merged.isnull().sum() / len(merged)
print(f"搜索指数缺失率: {missing_report['search_volume']:.2%}")

3.6 案例拆解:某海岛度假酒店的需求预测数据工程

背景与约束:某海岛度假酒店(300间客房)需要搭建未来 90 天的入住率预测模型。酒店 60% 订单来自 OTA 渠道,40% 来自官网直销。历史数据从 2019 年至今,中间经历了疫情导致的停业期(2020年2-4月)。业务方要求预测结果每日更新,且需区分平日与周末的差异。

初始现象与目标:初步建模时发现,直接使用原始预订数据训练,模型在节假日预测误差高达 40%。排查发现三个问题:① 2020年疫情停业期数据未剔除,导致模型低估旺季需求;② OTA 渠道的预订提前期(lead time)平均为 45 天,而官网直销仅 15 天,混合建模导致特征失效;③ 天气数据使用的是实况而非预报,造成特征泄漏。

关键操作步骤:

  1. 数据清洗:剔除 2020年2-4月停业期数据,单独标记为"异常经营期";对取消标记缺失的订单,按渠道分别计算取消率并随机插补。
  2. 异常值处理:发现 2023年国庆期间预订量是历史均值的 4.2 倍,经核实为真实需求,保留并添加"黄金周"事件标签。
  3. 时间对齐:将搜索指数(小时级)重采样为日粒度,并构造 7/14/21 天滞后特征;天气数据使用预报值而非实况值,避免特征泄漏。
  4. 渠道分离:分别构建 OTA 渠道和直销渠道的预测模型,最终加权融合。OTA 模型侧重提前期特征,直销模型侧重会员活跃度特征。

结果对比:优化后,节假日预测 MAPE 从 40% 降至 18%,平日预测 MAPE 从 15% 降至 9%。代价是数据管道复杂度提升,每日调度时间从 20 分钟增加到 45 分钟,但仍在业务可接受范围内。

复盘经验:数据清洗不是一次性工作,而是需要建立数据质量监控看板,每日跟踪缺失率、异常值数量、时间对齐完整性三个核心指标。当新增数据源或业务规则变化时,必须重新评估清洗策略。

总结复盘:数据准备与清洗占整个预测项目 60% 以上的工作量。核心原则是:先理解业务,再处理数据。不要盲目追求数据量的增加,而应关注数据质量的稳定性和特征的可解释性。建议建立数据版本管理机制,每次清洗逻辑变更后重新生成数据集,并记录变更日志,确保模型实验的可复现性。