Python 数据分析:时间序列

本文详细介绍了Python中处理时间序列数据的方法,包括日期时间数据类型、时间序列基础、日期范围、频率和移位、时区处理、时间区间算数、重新采样与频率转换以及移动窗口函数。讲解了如何使用datetime、pandas、Timestamp、DatetimeIndex等工具进行时间序列分析,涵盖了日期的转换、索引、选择、子集操作,时区的本地化和转换,以及时间序列的重采样和移动窗口函数的应用。
摘要由CSDN通过智能技术生成

1. 日期和时间数据的类型及工具

  • Python 的标准库包含日期、时间、日历等相关模块。其中 datetime, time, calender 是处理时间数据的主要内容。datetime.datetime 类是最常用的

  • datetime.now() 获取当前的时间

import pandas as pd
import numpy as np
from datetime import datetime
now = datetime.now()
now
datetime.datetime(2019, 8, 11, 14, 17, 29, 402021)
  • datetime 既存储了日期,也存储了细化到微秒的时间
now.year, now.month, now.day
(2019, 8, 11)
  • timedelta 表示两个 datetime 对象的时间差
delta = datetime(2019, 1, 1) - datetime(2018, 8, 8, 10, 10)
print(delta, delta.days, delta.seconds, sep='\n')
145 days, 13:50:00
145
49800
  • 为 datetime 对象加上(或减去)一个 timedelta 或其整数倍来产生一个新的 datetime 对象
from datetime import timedelta
start = datetime(2019, 8, 1)
start + timedelta(12) * 2
datetime.datetime(2019, 8, 25, 0, 0)

datetime 模块中的类型表格

类型 描述
date 使用公历日历存储日历日期(年月日)
time 将时间存储为小时、分钟、秒和微秒
datetime 存储日期和时间
timedelta 表示两个 datetime 值之间的差(如日、秒和微秒)
tzinfo 用于存储时区信息的基本类型

1.1 字符串与 datetime 互相转换

  • 使用 str 方法或传递一个指定的格式给 strftime 方法来对 datetime 对象和 pandas 的 Timestamp 对象进行格式化
stamp = datetime(2019, 8, 1)
print(str(stamp))
print(stamp.strftime('%Y-%m-%d'))
2019-08-01 00:00:00
2019-08-01
  • 使用 datetime.strptime 将字符串转换为日期
value = '2019-08-01'
print(datetime.strptime(value, '%Y-%m-%d'))
datestrs = ['8/1/2019', '8/2/2019']
print([datetime.strptime(x, '%m/%d/%Y') for x in datestrs])
2019-08-01 00:00:00
[datetime.datetime(2019, 8, 1, 0, 0), datetime.datetime(2019, 8, 2, 0, 0)]
  • 使用 dateutil 的 parser.parse 方法解析大部分人类可理解的日期表示
from dateutil.parser import parse
print(parse('2019-08-01'))
print(parse('Aug 1, 2019 10:00 PM'))
print(parse('1/8/2019', dayfirst=True))    # dayfirst=True 表明日期在月份之前
2019-08-01 00:00:00
2019-08-01 22:00:00
2019-08-01 00:00:00
  • 使用 pandas.to_datetime 将日期表示转换为 DataFrame 的索引
datestrs = ['2019-08-01 12:00:00', '2019-08-02 00:00:00']
print(pd.to_datetime(datestrs))
# to_datetime 还可以处理缺失值
idx = pd.to_datetime(datestrs + [None])
print(idx)
print(pd.isnull(idx))
DatetimeIndex(['2019-08-01 12:00:00', '2019-08-02 00:00:00'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2019-08-01 12:00:00', '2019-08-02 00:00:00', 'NaT'], dtype='datetime64[ns]', freq=None)
[False False  True]

datetime 格式说明(兼容 ISO C89)(基础知识部分也有该表格)

https://blog.csdn.net/u012470887/article/details/92431590

类型 描述
%Y 四位的年份
%y 两位的年份
%m 两位的月份[01, 12]
%d 两位的天数值 [01, 31]
%H 小时值(24 小时制)[00, 23]
%I 小时值(12 小时制)[01, 12]
%M 两位的分钟值 [00, 59]
%S 秒值 [00, 61] (60, 61用于区分闰秒)
%w 星期值 [0(星期天), 6]
%U 一年中的第几个星期值 [00, 53],星期天为每周第一天,第一个星期天前一周是第0周
%W 一年中的第几个星期值 [00, 53],星期一为每周第一天,第一个星期一前一周是第0周
%z UTC 时区偏置,格式为 +HHMM 或 -HHMM,如果是简单时区则为空
%F %Y-%m-%d 的简写
%D %m/%d/%y 的简写

2. 时间序列基础

  • pandas 中的基础时间序列种类是由时间戳索引的 Series, 在 pandas 外部则通常表示为 Python 字符串或 datetime 对象
from datetime import datetime
dates = [datetime(2019, 8, 1), datetime(2019, 8, 5),
        datetime(2019, 8, 7), datetime(2019, 8, 8),
        datetime(2019, 8, 10), datetime(2019, 8, 12)]
ts = pd.Series(np.random.randn(6), index=dates)
ts
2019-08-01    0.468772
2019-08-05    2.333443
2019-08-07   -0.502920
2019-08-08    1.145697
2019-08-10   -0.504389
2019-08-12   -1.343926
dtype: float64
  • 这种情况下,这些 datetime 对象可以被放入 DatetimeIndex 中
ts.index
DatetimeIndex(['2019-08-01', '2019-08-05', '2019-08-07', '2019-08-08',
               '2019-08-10', '2019-08-12'],
              dtype='datetime64[ns]', freq=None)
  • 和其他 Series 一样,不同索引的时间序列之间的算术运算在日期上自动对齐
ts + ts[::2]
2019-08-01    0.937543
2019-08-05         NaN
2019-08-07   -1.005840
2019-08-08         NaN
2019-08-10   -1.008777
2019-08-12         NaN
dtype: float64
  • DatetimeIndex 中的标量值是 pandas 的 Timestamp 对象
stamp = ts.index[0]
stamp
Timestamp('2019-08-01 00:00:00')

2.1 索引、选择、子集

  • 基于标签进行索引和选择时,时间序列的行为和其他的 pandas.Series 类似
stamp = ts.index[2]
s[stamp]
-0.5029199053879977
  • 为了方便,可以传递一个能被解释为日期的字符串
print(ts['8/1/2019'])
print(ts['20190801'])
0.46877169482728676
0.46877169482728676
  • 对于一个长的时间序列,可以传递一个年份或一个年份和月份来选择数据的切片
longer_ts = pd.Series(np.random.randn(1000), 
                     index=pd.date_range('1/1/2017', periods=1000))
print(longer_ts[:10], longer_ts['2018'][:10], longer_ts['2018-05'][:10], sep='\n' + '*' * 10 + '\n')
2017-01-01   -1.000006
2017-01-02   -0.012311
2017-01-03    1.290370
2017-01-04   -1.411002
2017-01-05   -1.043768
2017-01-06   -2.026386
2017-01-07    0.923300
2017-01-08   -1.159909
2017-01-09   -0.340406
2017-01-10   -2.195334
Freq: D, dtype: float64
**********
2018-01-01   -0.614101
2018-01-02    0.034989
2018-01-03   -0.816531
2018-01-04   -0.025899
2018-01-05    1.499072
2018-01-06   -0.025201
2018-01-07   -1.936647
2018-01-08    0.748457
2018-01-09   -0.159147
2018-01-10   -1.762938
Freq: D, dtype: float64
**********
2018-05-01    1.912698
2018-05-02   -0.614768
2018-05-03    3.010737
2018-05-04   -0.828237
2018-05-05    0.866249
2018-05-06   -0.035166
2018-05-07   -1.222878
2018-05-08    0.541532
2018-05-09    1.337297
2018-05-10   -1.633647
Freq: D, dtype: float64
  • 也可以使用 datetime 对象进行切片,由于大部分时间序列数据是按时间顺序排序的,因此可以使用不包含在时间序列中的时间戳进行切片,以执行范围查询
ts[datetime(2019, 8, 4): datetime(2019, 8, 10)]
2019-08-05    2.333443
2019-08-07   -0.502920
2019-08-08    1.145697
2019-08-10   -0.504389
dtype: float64
  • 使用 truncate() 方法也可以实现在两个日期间对 Series 进行切片
ts.truncate(before='8/2/2019', after='8/8/2019')
2019-08-05    2.333443
2019-08-07   -0.502920
2019-08-08    1.145697
dtype: float64
  • 上面的操作也同样适用于 DataFrame,并在其行上进行索引
dates = pd.date_range('1/1/2018', periods=100, freq='W-WED')
long_df = pd.DataFrame(np.random.randn(100, 4),
                      index=dates,
                      columns=['Colorado', 'Texas', 'Nwe York', 'Ohio'])
long_df[:10]
Colorado Texas Nwe York Ohio
2018-01-03 -0.865582 1.623844 -0.200563 -1.166387
2018-01-10 0.441938 1.022298 -0.834719 -0.125343
2018-01-17 -0.767586 -0.434506 0.008906 -0.359749
2018-01-24 0.151662 -0.904767 -1.224332 1.169810
2018-01-31 -0.172146 -0.495993 0.841341 -0.080990
2018-02-07 0.485385 -1.327956 0.144750 0.294078
2018-02-14 -0.071519 1.098334 -0.923484 -1.466727
2018-02-21 -0.482320 -0.122691 -0.719345 -1.044682
2018-02-28 0.160908 1.044807 -0.020349 -0.426059
2018-03-07 -0.009414 0.081428 -0.523577 1.182005
long_df.loc['5-2018']
Colorado Texas Nwe York Ohio
2018-05-02 -1.519427 -0.158811 1.191555 1.005464
2018-05-09 -0.704590 -0.332483 0.096710 -0.031565
2018-05-16 0.062633 0.375264 -0.321858 -0.776452
2018-05-23 -1.657576 -0.445090 -0.718661 -1.409694
2018-05-30 0.153913 0.402754 1.435081 -0.883503

2.2 含有重复索引的时间序列

  • 对于有些数据,可能在某个特定的时间戳上有多个数据,导致索引重复,可以调用索引对象的 is_unique 属性查看是否重复,对于不重复的索引,其索引的结果为标量值,对于重复的索引,其索引结果为 Series 的切片
dates = pd.DatetimeIndex(['1/1/2019', '1/2/2019', '1/2/2019', '1/2/2019', '1/3/2019'])
dup_ts = pd.Series(np.arange(5
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值