18. 日期时间处理1. 概述日期和时间数据在数据分析中非常常见如订单时间、用户注册时间、日志时间戳等。Pandas 提供了强大的日期时间处理功能支持日期解析、时间范围生成、日期提取、时间差计算等操作。importpandasaspdimportnumpyasnp# 创建包含日期时间的示例数据dfpd.DataFrame({订单号:[ORD001,ORD002,ORD003,ORD004,ORD005],订单日期:[2024-01-15,2024/02/20,2024年03月10日,15-04-2024,2024-05-25],下单时间:[2024-01-15 09:30:00,2024-02-20 14:15:00,2024-03-10 10:45:00,2024-04-15 16:20:00,2024-05-25 11:00:00],发货时间:[2024-01-16 10:00:00,2024-02-21 09:30:00,2024-03-12 14:00:00,2024-04-17 08:30:00,2024-05-26 15:00:00]})print(原始数据:)print(df)print(\n数据类型:)print(df.dtypes)2. 日期时间类型转换2.1 pd.to_datetime() 基础# 单列转换df[订单日期_转换]pd.to_datetime(df[订单日期])print(订单日期转换结果:)print(df[[订单日期,订单日期_转换]])print(f\n转换后类型:{df[订单日期_转换].dtype})# 处理多种格式df[下单时间_转换]pd.to_datetime(df[下单时间])print(f\n下单时间类型:{df[下单时间_转换].dtype})2.2 处理转换错误# 创建包含无效日期的数据df_badpd.DataFrame({日期:[2024-01-01,invalid,2024-01-03,not a date,2024-01-05]})print(原始数据:)print(df_bad)# errorscoerce 将无效值转为 NaTdf_bad[日期_转换]pd.to_datetime(df_bad[日期],errorscoerce)print(\n转换结果无效值变为 NaT:)print(df_bad)# 查看转换失败的记录invalid_datesdf_bad[df_bad[日期_转换].isna()]print(f\n转换失败的记录:{len(invalid_dates)}条)2.3 指定日期格式# 使用 format 参数指定格式提高转换速度df_formatpd.DataFrame({日期:[2024-01-15,2024-02-20,2024-03-10]})df_format[日期_转换]pd.to_datetime(df_format[日期],format%Y-%m-%d)print(指定格式转换:)print(df_format)# 常见日期格式对照# %Y: 4位年, %y: 2位年# %m: 月, %d: 日# %H: 24小时, %I: 12小时, %p: AM/PM# %M: 分钟, %S: 秒3. 日期时间属性提取# 转换日期列df[订单日期_dt]pd.to_datetime(df[订单日期])df[下单时间_dt]pd.to_datetime(df[下单时间])# 提取日期各部分print(日期各部分:)print(f年:{df[订单日期_dt].dt.year})print(f月:{df[订单日期_dt].dt.month})print(f日:{df[订单日期_dt].dt.day})print(f星期几数字:{df[订单日期_dt].dt.dayofweek})print(f星期几名称:{df[订单日期_dt].dt.day_name()})print(f年中的第几天:{df[订单日期_dt].dt.dayofyear})print(f季度:{df[订单日期_dt].dt.quarter})print(f是否月末:{df[订单日期_dt].dt.is_month_end})# 提取时间各部分print(\n时间各部分:)print(f小时:{df[下单时间_dt].dt.hour})print(f分钟:{df[下单时间_dt].dt.minute})print(f秒:{df[下单时间_dt].dt.second})4. 时间差计算# 计算发货时长df[发货时长]df[发货时间_dt]-df[下单时间_dt]print(发货时长:)print(df[[订单号,下单时间,发货时间,发货时长]])# 提取时间差各部分print(\n时间差详情:)print(f天数:{df[发货时长].dt.days})print(f秒数部分:{df[发货时长].dt.seconds})print(f总秒数:{df[发货时长].dt.total_seconds()})print(f小时数:{df[发货时长].dt.total_seconds()/3600:.1f})5. 日期偏移与滚动5.1 日期加减frompandas.tseries.offsetsimportDateOffset# 使用 DateOffsetdf[预计送达]df[订单日期_dt]pd.DateOffset(days3)print(预计送达日期:)print(df[[订单日期_dt,预计送达]])# 使用 timedeltafromdatetimeimporttimedelta df[一周后]df[订单日期_dt]timedelta(days7)print(\n一周后:)print(df[[订单日期_dt,一周后]])# 月份加减处理月末边界df[下个月]df[订单日期_dt]pd.DateOffset(months1)print(\n下个月:)print(df[[订单日期_dt,下个月]])5.2 日期移动shift# 创建时间序列数据np.random.seed(42)tspd.DataFrame({日期:pd.date_range(2024-01-01,periods10,freqD),销售额:np.random.randint(100,500,10)})# 计算环比ts[前一日销售额]ts[销售额].shift(1)ts[环比变化]ts[销售额]-ts[前一日销售额]ts[环比增长率](ts[环比变化]/ts[前一日销售额]*100).round(2)print(销售环比分析:)print(ts)6. 时间范围与重采样6.1 生成日期范围# 生成日期范围date_rangepd.date_range(start2024-01-01,end2024-01-10,freqD)print(每日范围:)print(date_range)# 按小时生成date_range_hourpd.date_range(start2024-01-01,periods10,freqH)print(\n小时范围:)print(date_range_hour)# 按工作日生成date_range_businesspd.date_range(start2024-01-01,periods10,freqB)print(\n工作日范围:)print(date_range_business)# 频率代码# D: 天, H: 小时, T: 分钟, S: 秒# B: 工作日, W: 周, M: 月末, MS: 月初# Q: 季末, QS: 季初, A: 年末, AS: 年初6.2 重采样resample# 创建分钟级数据np.random.seed(42)minutes_datapd.DataFrame({时间:pd.date_range(2024-01-01 09:00:00,periods60,freqT),值:np.random.randn(60).cumsum()})minutes_data.set_index(时间,inplaceTrue)print(原始分钟数据前5行:)print(minutes_data.head())# 重采样为小时取平均值hourly_meanminutes_data.resample(H).mean()print(\n小时均值:)print(hourly_mean)# 重采样为小时取总和hourly_summinutes_data.resample(H).sum()print(\n小时总和:)print(hourly_sum)# 多种聚合hourly_aggminutes_data.resample(H).agg([mean,max,min,std])print(\n多种统计:)print(hourly_agg.head())7. 滑动窗口计算# 创建时间序列df_tspd.DataFrame({日期:pd.date_range(2024-01-01,periods30,freqD),销售额:np.random.randint(100,300,30)})df_ts.set_index(日期,inplaceTrue)# 7日移动平均df_ts[MA7]df_ts[销售额].rolling(window7).mean()# 7日移动总和df_ts[SUM7]df_ts[销售额].rolling(window7).sum()# 扩展窗口从开始到当前df_ts[累计平均]df_ts[销售额].expanding().mean()print(滑动窗口计算:)print(df_ts.head(15))8. 完整示例电商订单分析# 创建订单数据np.random.seed(42)orderspd.DataFrame({订单号:[fORD{i:05d}foriinrange(1,101)],下单时间:pd.date_range(2024-01-01 00:00:00,periods100,freqH),金额:np.random.uniform(50,1000,100).round(2),状态:np.random.choice([已完成,已取消,处理中],100,p[0.7,0.1,0.2])})# 添加随机发货时间orders[发货时间]orders[下单时间]pd.to_timedelta(np.random.randint(1,72,100),unith)orders.loc[orders[状态]已取消,发货时间]pd.NaTprint(*60)print(电商订单时间分析)print(*60)# 1. 提取时间特征print(\n1. 时间特征提取:)orders[下单日期]orders[下单时间].dt.date orders[下单小时]orders[下单时间].dt.hour orders[下单星期]orders[下单时间].dt.day_name()orders[下单月份]orders[下单时间].dt.monthprint(orders[[订单号,下单时间,下单小时,下单星期]].head())# 2. 计算发货时长orders[发货时长(小时)](orders[发货时间]-orders[下单时间]).dt.total_seconds()/3600print(\n2. 发货时长统计:)print(orders[orders[状态]已完成][发货时长(小时)].describe())# 3. 按小时统计订单量print(\n3. 各小时订单量分布:)hourly_ordersorders.groupby(下单小时).size().sort_index()print(hourly_orders)# 4. 按星期统计销售额print(\n4. 各星期销售额:)weekday_salesorders.groupby(下单星期)[金额].sum().sort_values(ascendingFalse)print(weekday_sales)# 5. 日销售额趋势print(\n5. 日销售额趋势:)daily_salesorders.set_index(下单时间).resample(D)[金额].sum()print(daily_sales.head(10))# 6. 7日移动平均ma7daily_sales.rolling(window7).mean()print(\n6. 7日移动平均前10天:)print(ma7.head(10))9. 常见日期格式代码代码说明示例%Y4位年2024%y2位年24%m2位月01%d2位日15%H24小时制14%I12小时制02%pAM/PMPM%M分钟30%S秒00%f微秒123456%a缩写星期Mon%A完整星期Monday%b缩写月份Jan%B完整月份January10. 总结方法用途示例pd.to_datetime()转换为日期时间pd.to_datetime(df[col])dt.year/month/day提取日期部分df[date].dt.yeardt.hour/minute/second提取时间部分df[time].dt.hourdt.day_name()星期名称df[date].dt.day_name()dt.quarter季度df[date].dt.quarterdate1 - date2计算时间差df[end] - df[start]pd.DateOffset()日期偏移df[date] pd.DateOffset(days7)shift()数据移动df[value].shift(1)pd.date_range()生成日期范围pd.date_range(2024-01-01, periods10)resample()重采样df.resample(D).mean()rolling()滚动窗口df.rolling(window7).mean()