时间序列数据在很多领域都是重要的结构化数据形式。
11.1 日期和时间数据的类型及工具
就是datetime ,time , calendar 模块
from datetime import datetime
now=datetime.now()
now
datetime.datetime(2020, 7, 13, 9, 58, 28, 291817)
now.year,now.month,now.day
(2020, 7, 13)
delta = datetime(2020,6,6)-datetime(2020,7,13,10,0) # timedelata表示时间差
delta
datetime.timedelta(days=-38, seconds=50400)
delta.days,delta.seconds
(-38, 50400)
from datetime import timedelta
start = datetime(2011, 1, 7)
start + timedelta(12)
datetime.datetime(2011, 1, 19, 0, 0) # 一个datetime对象加上/减去一个timedelta 或其整数倍
start - 2 * timedelta(12)
datetime.datetime(2010, 12, 14, 0, 0)
datetime模块的类型 | 描述 |
---|---|
date | 使用公历日历储存日历日期 |
time | 将时间储存为小时分钟秒和微妙 |
datetime | 储存日期和时间,就是上面两个合体 |
timedelta | 表示一个时间差 |
tzinfo | 用于存储失去信息的基本类型 |
11.1.1 字符串和datetime 互相转换
stamp=datetime(2020,7,13)
str(stamp) # 使用str() or strftime来格式化,相关格式说明符不在啰嗦了。。。
'2020-07-13 00:00:00'
stamp.strftime('%Y-%m-%d')
'2020-07-13'
value='2020-06-06'
datetime.strptime(value,'%Y-%m-%d')
datetime.datetime(2020, 6, 6, 0, 0)
datestrs = ['7/6/2011', '8/6/2011']
[datetime.strptime(x, '%m/%d/%Y') for x in datestrs]
[datetime.datetime(2011, 7, 6, 0, 0), datetime.datetime(2011, 8, 6, 0, 0)]
from dateutil.parser import parse # strptime 每次都要写一个格式代码,使用这个包的parse方法可以解析大部分日期
parse('2011-01-03')
datetime.datetime(2011, 1, 3, 0, 0) # 这个包在按照pandas时就已经安装好了
parse('Jan 31, 1997 10:45 PM')
datetime.datetime(1997, 1, 31, 22, 45)
parse('6/12/2011', dayfirst=True) # 这是说明日期出现在月份之前。
datetime.datetime(2011, 12, 6, 0, 0)
datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00'] # pandas主要是面向处理日期数组的
pd.to_datetime(datestrs) # 可以用作轴索引或dataframe中的列。to_datetime可以快速的转换很多不同的日期格式
idx = pd.to_datetime(datestrs + [None]) # 还可以处理那些被认为时缺失值的值,None,空字符串等)
idx # NaT 时pandas中时间戳数据的缺失值
DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00', 'NaT'], dtype='datetime64[ns]', freq=None)
11.2 时间序列基础
pandas中的基础时间序列种类是由时间戳索引的series,在pandas外部则通常表示为python字符串或datetime对象
dates = [datetime(2011, 1, 2), datetime(2011, 1, 5),
datetime(2011, 1, 7), datetime(2011, 1, 8),
datetime(2011, 1, 10), datetime(2011, 1, 12)]
ts = pd.Series(np.random.randn(6), index=dates)
ts
2011-01-02 -0.275580
2011-01-05 1.045973
2011-01-07 -0.985276
2011-01-08 0.924392
2011-01-10 0.419848
2011-01-12 0.614852
dtype: float64
ts.index # 这种情况下,这些datetime对象可以被放到datetimeindex中。
DatetimeIndex(['2011-01-02', '2011-01-05', '2011-01-07', '2011-01-08',
'2011-01-10', '2011-01-12'],
dtype='datetime64[ns]', freq=None)
ts + ts[::2] # 不同索引的时间序列之间的算术运算在日期上自动对齐。
2011-01-02 -0.551159
2011-01-05 NaN
2011-01-07 -1.970552
2011-01-08 NaN
2011-01-10 0.839696
2011-01-12 NaN
dtype: float64
ts.index.dtype # pandas使用numpy 的 datetime64数据类型在纳秒级的分辨率下存储时间戳
dtype('<M8[ns]')
stamp = ts.index[0]
stamp
Timestamp('2011-01-02 00:00:00') # datetimeIndex对象的标量值时pandas的Timestamp对象。
11.2.1 索引,选择,子集
当你基于标签进行索引和选择时,时间序列的行为和其他pandas.sereis类似
stamp = ts.index[2]
ts[stamp]
2.3621857850047703 # 更上面不对应哈。。。重搞了个
ts['1/10/2011']
ts['20110110'] # 为了方便还可以传递一个能解释为日期的字符串。
# 对于一个长的时间序列,可以传递一个年份或一个年份的和月份来选择数据的切片
longer_ts = pd.Series(np.random.randn(1000),
index=pd.date_range('1/1/2000', periods=1000))
longer_ts['2001']
2001-01-01 0.582780
2001-01-02 -0.385715
2001-01-03 0.452116
2001-01-04 -0.691663
2001-01-05 0.276754
...
2001-12-27 -0.663968
2001-12-28 0.654027
2001-12-29 0.602500
2001-12-30 -0.336441
2001-12-31 1.298244
Freq: D, Length: 365, dtype: float64
longer_ts['2001-05'] # 指定月份也是有效的
s[datetime(2011, 1, 7):] # 使用datetime对象切片
ts # 大部分的时间序列都是按时间顺序排序的,你可以使用不包含在时间序列中的时间戳进行切片,以执行范围查询。
2011-01-02 -0.951803
2011-01-05 -1.225867
2011-01-07 2.362186
2011-01-08 0.315127
2011-01-10 0.979435
2011-01-12 1.538739
dtype: float64
ts['1/6/2011':'1/11/2011'] # 是没有6 11号的
2011-01-07 2.362186
2011-01-08 0.315127
2011-01-10 0.979435
dtype: float64
# 这些方式产生的切片时原序列的视图,不是复制,修改也会反应在原序列上。
ts.truncate(after='1/9/2011') # 可以在两个日期间对series进行切片
2011-01-02 -0.951803
2011-01-05 -1.225867
2011-01-07 2.362186
2011-01-08 0.315127
dtype: float64
dates = pd.date_range('1/1/2000', periods=100, freq='W-WED')
long_df = pd.DataFrame(np.random.randn(100, 4),
index=dates,
columns=['Colorado', 'Texas',
'New York', 'Ohio'])
long_df.loc['5-2001']
Colorado Texas New York Ohio
2001-05-02 0.800274 0.276801 -1.558333 0.158561 # 上面的操作也对dataframe 使用
2001-05-09 -1.020414 -0.544250 1.597216 0.389963
2001-05-16 -0.485741 1.529283 0.155557 0.381811
2001-05-23 2.134218 2.234055 -0.621261 0.091993
2001-05-30 0.054316 -2.945546 0.710821 1.333699
11.2.2 含有重复索引的时间序列
dates = pd.DatetimeIndex(['1/1/2000', '1/2/2000', '1/2/2000',
'1/2/2000', '1/3/2000'])
dup_ts = pd.Series(np.arange(5), index=dates)
dup_ts
2000-01-01 0
2000-01-02 1
2000-01-02 2
2000-01-02 3 # 多个数据观察值落到特定的时间戳上,
2000-01-03 4
dtype: int32
dup_ts.index.is_unique # 检测这个属性,可以看到索引并不唯一
False
dup_ts['1/3/2000'] # 不重复的
4
dup_ts['1/2/2000'] # 索引出来的是重复的
2000-01-02 1
2000-01-02 2
2000-01-02 3
dtype: int32
grouped = dup_ts.groupby(level=0) # 想要将非唯一时间戳聚合可以使用groupby,并传递level-0
grouped.count()
2000-01-01 1
2000-01-02 3
2000-01-03 1
dtype: int64