处理日期与时间
在数据分析中,日期和时间数据的处理是非常基础且重要的环节,合理运用相关工具能让我们更高效地从时间维度挖掘数据价值。接下来,我们将从日期数据的处理、日期范围与频率、时间区间转换、重新采样以及移动窗口函数这几个方面展开。
一、日期数据的处理
首先,我们来看日期数据的处理,这部分主要包括日期数据的转换、dt 对象的使用、指定日期区间数据的获取以及按不同时期统计数据。
1. 日期数据的转换
在实际操作中,我们拿到的日期数据往往格式多样,比如 “2023 年 2 月 14 日”“14-Feb-23”“2023/02/14” 等,这时候就需要将它们统一转换为标准的日期格式。pandas 中的to_datetime()方法就是专门用来做这个的。
to_datetime()方法的参数很丰富,比如errors可以处理无效的日期格式,设置为coerce时会将无效值转为NaT(类似 NaN 的日期型空值);format可以指定日期格式,提高转换效率;unit则适用于 Unix 时间戳的转换。例如,我们可以用它将各种格式的 “2023 年 2 月 14 日” 统一转为 “2023-02-14” 这种标准格式,方便后续处理。
另外,我们还可以将分散的年、月、日等数据组合成日期,比如有 “year=2023”“month=2”“day=14” 这样的列,通过to_datetime()也能快速合并成完整的日期数据。
2. dt 对象
当我们将数据转换为日期格式后,就可以使用dt对象来提取日期中的详细信息。dt对象提供了很多实用的属性和方法,比如year(年份)、month(月份)、day(日)、dayofweek(星期几)、quarter(季度)、is_leap_year(是否闰年)等。
举个例子,对于 “2022-12-31” 这个日期,通过dt.year可以得到 2022,dt.month得到 12,dt.day得到 31,dt.dayofweek能知道这一天是星期六,dt.quarter显示为第 4 季度,dt.is_leap_year则会返回 False(2022 年不是闰年)。借助这些属性,我们能轻松实现按年、月、季度等维度的分析。
3. 获取指定日期区间的数据
在分析时,我们常常需要筛选出某一时间段的数据。如果日期是数据的索引,操作会非常便捷:
- 要获取 2022 年的数据,直接用df.loc['2022'];
- 获取 2021 至 2022 年的数据,用df['2021':'2022'];
- 精确到月份,比如 2022 年 7 月,用df.loc['2022-07'];
- 甚至可以精确到某一天,比如 2022 年 5 月 6 日,用df['2022-05-06':'2022-05-06']。
比如我们要分析 2022 年 5 月 11 日到 6 月 10 日的订单数据,就可以用类似的方法快速筛选出这段时间的记录,方便后续统计。
4. 按不同时期统计数据
按不同时期统计数据主要用到resample()和to_period()方法。
- resample()方法可以按年('AS')、季度('Q')、月('M')、星期('W')、天('D')等频率对数据进行汇总,比如df.resample('M').sum()就是按月统计数据总和。
- to_period()方法则用于将日期转换为对应的时期索引,比如df.to_period('A')会将日期转为按年的时期,df.to_period('M')转为按月的时期,让数据的时间维度更清晰。
我们还可以将两者结合,比如df.resample('Q').sum().to_period('Q'),就是按季度统计数据后,再以季度时期索引显示结果,看起来更直观。
二、日期范围、频率和移位
接下来我们学习日期范围的生成、频率转换以及日期移位的操作。
1. 生成日期范围 ——date_range()函数
date_range()函数可以帮我们生成指定范围和频率的日期序列,非常适合创建时间索引。它的主要参数有start(起点)、end(终点)、periods(日期数量)、freq(频率)等。
比如:
- pd.date_range('2023/1/1','2023/1/3')会生成 2023 年 1 月 1 日到 3 日的每日日期(默认 freq='D');
- freq='B'表示只生成工作日;
- freq='H'按小时生成;
- 甚至可以用复合频率,比如freq='7D'(每 7 天)、freq='1h30min'(每 1 小时 30 分钟)。
通过这些参数,我们能灵活生成各种时间序列,满足不同场景的需求。
2. 日期频率转换 ——asfreq()方法
asfreq()方法用于改变日期数据的频率,比如将按天的数据转换为按 5 小时的数据。转换后,原日期对应的值会填充到新频率的每个时间点上。例如,2023-01-01 的数据是 0.898176,转换为 5 小时频率后,2023-01-01 00:00、05:00、10:00 等时间点都会显示这个值,方便我们按更细的时间粒度分析数据。
3. 移位日期 ——shift()方法
日期移位和我们之前学过的数据移位类似,通过shift()方法可以将日期数据向前或向后移动指定幅度。periods参数控制移动次数(正数向后移,负数向前移),freq参数(仅用于时间序列)可以移动日期索引而保持数据不变。
比如,将 2023 年 1 月 1 日到 5 日的数据向前移动 2 次,前两条数据会变成NaN,后面的数据依次前移;向后移动 2 次则相反,后两条数据变为NaN。这在计算环比变化(如本周与上周数据对比)时非常有用。
三、时间区间与频率转换
这部分我们主要学习时间区间的创建和区间频率的转换。
1. 创建时间区间
- Period 类:用于表示单个时间区间,比如Period('2023', freq='A')表示 2023 年这个年度区间,我们可以通过它的start_time和end_time属性获取区间的起止时间(2023-01-01 00:00:00 到 2023-12-31 23:59:59.999999999)。
- period_range () 函数:用于生成多个连续的时间区间,比如period_range('2022-01-01', '2022-06-30', freq='M')会生成 2022 年 1 月到 6 月的月度区间序列。
2. 区间频率转换
同样可以用asfreq()方法实现时间区间的频率转换,比如将年度区间 “2023” 转换为月度区间,会得到 “2023-01” 到 “2023-12” 的 12 个月度区间;转换为日历日区间则是 “2023-01-01” 到 “2023-12-31”。how参数可以指定区间的起止点(start或end),默认是end。
四、重新采样与频率转换
重新采样是指将时间序列数据从一个频率转换为另一个频率,主要分为降采样和升采样。
1. 重采样 ——resample()方法
resample()方法是实现重采样的核心工具,参数rule指定目标频率,how指定聚合函数(如求和、均值)。比如将一分钟的时间序列转换为 3 分钟的,就可以用df.resample('3T').sum(),对每 3 分钟的数据求和。
2. 降采样处理
降采样是将高频率数据转换为低频率数据(比如分钟→小时、天→周)。例如,我们有每天的销售数据,要按周统计,就可以用df.resample('W').sum(),将每周 7 天的销售额汇总,得到每周的总销量。这样能简化数据,展示更长周期的趋势。
3. 升采样处理
升采样则是将低频率数据转换为高频率数据(比如周→天、天→小时),这时候会出现空值,需要进行填充:
- 不填充:用asfreq()方法,空值保留NaN;
- 前值填充:用ffill()或pad()方法,用前面的已知值填充后面的空值;
- 后值填充:用bfill()方法,用后面的已知值填充前面的空值。
比如将 2 天的数据升采样为每 6 小时一次,用前值填充后,当天的每个 6 小时区间都会显示当天的数据,让数据更连贯。
五、移动窗口函数
最后,我们来学习移动窗口函数,它能帮助我们计算时间序列中固定长度窗口内的统计量。
1. 时间序列数据汇总 ——ohlc()函数
ohlc()函数用于汇总每组时间区间内的数据,返回open(起始值)、high(最大值)、low(最小值)、close(结束值)。比如对 5 分钟的时间序列,df.resample('10T').ohlc()会每 10 分钟统计一次这四个值,常用于金融数据等场景。
2. 移动窗口数据计算 ——rolling()函数
rolling()函数可以创建一个移动窗口,计算窗口内数据的统计量(如均值、求和)。它的window参数指定窗口大小(可以是数据个数或时间偏移),min_periods指定窗口内最少需要的非空值数量。
例如,计算 3 天的移动平均销量,df.rolling(window=3).mean()会依次计算每连续 3 天的销量均值;设置min_periods=1时,即使窗口内只有 1 个数据(如开头的前两个窗口),也会计算结果,而不是返回NaN。这在分析数据的短期趋势(如近 7 天平均销量)时非常实用。
总结
以上说明了从日期数据的转换、提取,到日期范围的生成、频率转换,再到重新采样和移动窗口计算,这些工具能帮助我们高效地从时间维度分析数据。无论是按年、季、月统计趋势,还是计算移动平均值,掌握这些方法都能让我们在处理时间序列数据时更方便。