趋近智
原始时间戳或日期字符串列虽然人类可读,但通常包含丰富的时间信息,机器学习模型无法直接以其原始形式理解。将日期仅仅当作标识符或连续数字来处理,通常会遗漏其内在规律,如季节性、趋势或特定的时间行为。从日期/时间特征中提取特定组成部分,使模型能够有效把握这些时间动态。
原始的时间戳或日期字符串列,尽管人类可读,但往往包含丰富的时序信息,而机器学习模型无法直接以其原始形式进行解释。将日期仅仅视为标识符或连续数字通常会忽略潜在的模式,如季节性、趋势或特定的时间行为。从日期/时间特征中提取特定组成部分,可以使模型有效捕捉这些时序动态。
在处理 Pandas DataFrame 中的数据时,第一步是确保您的日期列实际存储为日期时间类型。通常可以使用 pd.to_datetime() 实现这一点。一旦格式正确,Pandas 提供了方便的 .dt 访问器来提取各种组成部分。
假设有一个 DataFrame df,其中包含一个 event_timestamp 列:
import pandas as pd
# 示例数据
data = {'event_timestamp': ['2023-01-15 08:30:00', '2023-07-22 14:05:00', '2024-12-01 21:00:00'],
'value': [10, 20, 15]}
df = pd.DataFrame(data)
# 确保数据类型正确
df['event_timestamp'] = pd.to_datetime(df['event_timestamp'])
# 提取组成部分
df['year'] = df['event_timestamp'].dt.year
df['month'] = df['event_timestamp'].dt.month
df['day'] = df['event_timestamp'].dt.day
df['hour'] = df['event_timestamp'].dt.hour
df['day_of_week'] = df['event_timestamp'].dt.dayofweek # 星期一=0, 星期日=6
df['day_of_year'] = df['event_timestamp'].dt.dayofyear
df['week_of_year'] = df['event_timestamp'].dt.isocalendar().week.astype(int) # 使用 isocalendar 获取 ISO 周数
df['quarter'] = df['event_timestamp'].dt.quarter
df['is_weekend'] = df['day_of_week'].isin([5, 6]).astype(int) # 星期六=5, 星期日=6
print(df)
这个简单的过程生成了几个新的数值特征,供模型使用。例如:
year 可以反映长期趋势。month 和 quarter 可以反映季节性(例如,第四季度销售额更高)。day_of_week 和 is_weekend 可以建模周度模式(例如,工作日和周末用户活动差异)。hour 可以反映日内变化(例如,网站访问高峰时段)。这些提取的特征对于典型的机器学习算法而言,通常比原始时间戳更有信息量。
一些提取的时间特征是周期性的。例如,month 从 1 到 12,然后又回到 1。类似地,day_of_week 从 0 到 6 循环。将这些直接表示为简单的整数(1、2、...、12 或 0、1、...、6)对某些模型,特别是基于距离的模型或线性模型,可能会有问题。模型可能会将月份 12 解释为与月份 1 相距很远,而实际上它们在周期中是相邻的。
表示周期性特征的一种常用技术是使用正弦和余弦变换将它们映射到圆上。这会创建两个特征,它们共同保持了周期性距离信息。
对于最大值为 max_val 的特征 x(例如,月份为 12,从 0 开始的星期几为 6),变换公式如下:
如果特征是基于 1 的索引(例如月份 1-12),分母可能就是 max_val。如果它是基于 0 的索引(例如 dayofweek 0-6),分母通常是 max_val + 1。请确保 x 的范围与使用的分母一致。
让我们将此应用于 month 和 day_of_week 特征:
import numpy as np
# 月份 (1-12)
df['month_sin'] = np.sin(2 * np.pi * df['month'] / 12)
df['month_cos'] = np.cos(2 * np.pi * df['month'] / 12)
# 星期几 (0-6)
df['dow_sin'] = np.sin(2 * np.pi * df['day_of_week'] / 7)
df['dow_cos'] = np.cos(2 * np.pi * df['day_of_week'] / 7)
# 如果需要,删除原始周期性特征
# df = df.drop(['month', 'day_of_week'], axis=1)
print(df[['event_timestamp', 'month_sin', 'month_cos', 'dow_sin', 'dow_cos']].head())
现在,月份 12 和 1 在 (month_sin, month_cos) 空间中将具有相似的值,这反映了它们在周期上的邻近性。星期几也是如此。
正弦和余弦变换将月份映射到一个圆上,保持了十二月(12)和一月(1)的邻近关系。
从日期/时间数据衍生的另一种有用的特征类型是事件之间或相对于特定参考点的持续时间或已逝时间。
order_date、ship_date),可以计算它们的差值:
# 假设 df['order_date'] 和 df['ship_date'] 都是 datetime 对象
df['processing_time'] = df['ship_date'] - df['order_date']
# 将 Timedelta 转换为数值单位,例如天数
df['processing_days'] = df['processing_time'].dt.total_seconds() / (60*60*24)
# 示例:自数据集中最早事件以来的时间
reference_date = df['event_timestamp'].min()
df['time_since_start'] = (df['event_timestamp'] - reference_date).dt.total_seconds()
# 示例:相对于特定日期(例如,今天,分析日期)的时间
analysis_date = pd.to_datetime('2024-01-01')
df['days_until_analysis'] = (analysis_date - df['event_timestamp']).dt.days
这些持续时间特征可以反映流程效率、客户保有期、事件发生的时间远近以及其他与时间相关的因素。
hour、is_weekend)与现有其他特征(例如 product_category)组合,创建交互项,这可能揭示更具体的模式(例如,某些产品的销售额在周末特定时间达到高峰)。从日期/时间列中提取有意义的信息是一项常见且有影响的特征工程任务。通过将原始时间戳转换为表示趋势、季节性、周期和持续时间的组成部分,您为机器学习模型提供了有价值的信号,以改进它们的预测性能。请记住,选择与您要解决的特定问题最相关的组成部分和转换方法。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造