目录
Pandas时间序列数据
时间序列数据在金融、经济、神经科学、物理学里都是一种重要的结构化的数据表现形式,以时间为基本组织领域内的观测值并进行相应的分析,即时间序列分析的主要目的是根据已有的历史数据对未来进行预测。经济数据中大多数以时间序列的形式给出。根据观察时间的不同,时间序列中的时间可以是年份、季度、月份或其他任何时间形式。pandas 最基本的时间序列类型就是以时间戳(TimeStamp)为 index 元素的 Series 类型。 Python和Pandas里提供大量的内建工具、模块可以用来创建时间序列类型的数据。
pandas 支持 4 种常见时间概念:
- 日期时间(Datetime):带时区的日期时间,类似于标准库的 datetime.datetime 。
- 时间差(Timedelta):绝对时间周期,类似于标准库的 datetime.timedelta。
- 时间段(Timespan):在某一时点以指定频率定义的时间跨度。
- 日期偏移(Dateoffset):与日历运算对应的时间段,类似于
dateutil 的 dateutil.relativedelta.relativedelta。
常用操作思维导图
其他操作笔记
时间戳
在线计算转换时间戳:
可以看到datetime 默认使用本地时区,1447344000
对应的是北京时间2015-11-13 00:00:00
;pd.to_datetime默认使用UTC时区,1447372800
对应的是UTC时间2015-11-13 00:00:00
使用带时区的时间字符串
from datetime import datetime
import pandas as pd
tm = '2015-11-13 00:00:00+08:00'
stmp1 = datetime.strptime(tm, "%Y-%m-%d %H:%M:%S%z")
stmp2 = pd.to_datetime(tm)
print(stmp1.timestamp()) # 输出:1447344000.0
print(stmp2.timestamp()) # 输出:1447344000.0
修改datetime的时间戳
from datetime import datetime
import pandas as pd
tm = '2015-11-13 00:00:00'
stmp1 = datetime.strptime(tm, "%Y-%m-%d %H:%M:%S")
stmp2 = pd.to_datetime(tm)
stmp1_pd = pd.Timestamp(stmp1, tz='UTC')
print(stmp1_pd.timestamp()) # 输出:1447372800.0
print(stmp2.timestamp()) # 输出:1447372800.0
指定pandas的时区为Asia/Shanghai时间
使用pd.Series.dt.tz_localize方法将日期时间数据本地化为目标时区。使用pd.Series.dt.tz_convert方法将日期时间数据从一种时区转换为另一种时区。
from datetime import datetime
import pandas as pd
tm = '2015-11-13 00:00:00'
stmp1 = datetime.strptime(tm, "%Y-%m-%d %H:%M:%S")
# 生成当前时间的时间戳,不指定时区
stmp2 = pd.Timestamp(tm, tz='Asia/Shanghai')
print(stmp1.timestamp()) # 输出:1447344000.0
print(stmp2.timestamp()) # 输出:1447344000.0
或者
from datetime import datetime
import pandas as pd
tm = '2015-11-13 00:00:00'
stmp1 = datetime.strptime(tm, "%Y-%m-%d %H:%M:%S")
# 生成当前时间的时间戳,不指定时区
stmp2 = pd.to_datetime(tm).tz_localize('Asia/Shanghai')
print(stmp1.timestamp()) # 输出:1447344000.0
print(stmp2.timestamp()) # 输出:1447344000.0
3.4 整列时间戳转换为北京时间
df['tmt']= pd.to_datetime(df['stamp'], unit='s', origin=pd.Timestamp('1970-01-01')).dt.tz_localize('Asia/Shanghai')
df['tm'] = df['tmt'].dt.strftime('%Y-%m-%d %H:%M:%S')
时间格式转换:可以使用pd.to_datetime()函数将字符串或数字转换为时间格式,例如pd.to_datetime(‘2022-01-01’)。如果需要指定时间格式,可以使用format参数,例如pd.to_datetime(‘2022-01-01’, format=‘%Y-%m-%d’)。
时区转换:可以使用tz_localize()函数将时间列本地化为某个时区,例如df[‘time’].dt.tz_localize(‘UTC’)。然后使用tz_convert()函数将其转换为另一个时区,例如df[‘time’].dt.tz_convert(‘Asia/Shanghai’)。
时间差计算:可以使用pd.Timedelta()函数计算两个时间之间的差值,例如pd.Timedelta(days=1)表示一天的时间差。也可以使用pd.DateOffset()函数进行更灵活的时间偏移计算,例如pd.DateOffset(months=3)表示三个月后的时间。
时间序列操作:pandas提供了丰富的时间序列操作函数,例如resample()函数对时间序列进行重采样,rolling()函数进行滚动窗口计算等。需要注意的是,这些函数默认使用的是本地时区的时间,如果需要在不同时区之间进行操作,需要先进行时区转换。
解析csv时间索引示例代码
import pandas
mydateparser = lambda x: pd.datetime.strptime(x, "%Y %m %d %H:%M:%S")
df = pd.read_csv("file.csv", sep='\t', names=['date_column', 'other_column'], parse_dates=['date_column'], date_parser=mydateparser)
‘‘‘
file.csv
2016 06 10 20:30:00 foo
2016 07 11 19:45:30 bar
2013 10 12 4:30:00 foo
parse_dates参数是要分析的列
date_parser是解析器函数
’’’
pandas读取sqlite,并处理缺测值
sqlite建表
创建数据表时,添加数据更新的时间戳,并设置为当地时区
CREATE TABLE tablename (
ID INTEGER PRIMARY KEY,
column1 TEXT,
column2 REAL,
timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
);
pandas读取sqlite,并处理缺测值
- 从数据库中读取指定表格的数据,并转化其中的时间戳为当地时区的时间。
- 根据数据中的起止时间和逐小时的时间间隔,创建一个包含完整时间范围的时间序列。 将数据中的重复时间点去除,并将数据的索引设置为时间。
- 查找时间序列中缺失的数据,填充缺失值。 重新设置数据的索引为按逐小时精度排列的时间戳,并将数据存储回数据库中。
def fix_data(engine, tb_name, stnm, stcd):
df = pd.read_sql(tb_name, engine)
df['tm'] = pd.to_datetime(df['tm']).dt.tz_localize('Asia/Shanghai')
print(df['tm'].shape[0]) # 63653
# 起止时间
_start = df['tm'].loc[df.index[0]]
_end = df['tm'].loc[df.index[-1]]
full_range = pd.date_range(start=_start, end=_end, freq='60min', tz='Asia/Shanghai')
print(full_range.shape[0]) # 63745
# 设置原始数据索引为时间
df = df.drop_duplicates(subset=['tm'], keep='last') # 去除重复时间
df['stamp'] = df['tm'].apply(lambda x: int(x.timestamp())) # 获取原始数据时间戳
df = df.set_index('tm', drop=True) # 设置原始数据索引为时间
# 查找缺测值
df = df.reindex(full_range)
na_index = df.index[df.val.isna()] # 获取这缺测数据的行序号
df = df.fillna({'val': 0, 'stnm': stnm, 'stcd': stcd}) # 填充缺测值
df = df.reset_index(names='tm') # 保留时间列,重新设置索引
scale = 60 * 60 # 原始数据精度为逐小时
df['stamp'] = df['tm'].apply(lambda x: int(x.timestamp()))
df['ID'] = df['stamp'].apply(lambda x: int((int(x) - 1447344000) / scale) + 1)
df = df.set_index('ID', drop=True)
print(df)
df.to_sql(tb_name, engine, if_exists='fail', index=True)
Pandas计算区间差值
import pandas as pd
# 创建一个包含时间序列数据的DataFrame
df = pd.DataFrame({'timestamp': ['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04'],
'value': [1, 2, 4, 8]})
# 将timestamp列转换为日期格式
df['timestamp'] = pd.to_datetime(df['timestamp'])
# shift和diff都包含参数periods,默认也均为1
# 计算区间差值,periods默认为1,后项减当前项
df['difference'] = df['value'].shift(-1) - df['value']
print(df)
df['difference'] = df['value'].diff(periods=1).shift(-1)
# 查看结果
print(df)
# 计算区间差值,periods默认为1,当前减后项
df['difference'] = df['value'] - df['value'].shift(1)
print(df)
# 计算相邻两天的值的差值,periods默认为1
df['difference'] = df['value'].diff(1)
# 查看结果
print(df)
# output
"""
timestamp value difference
0 2021-01-01 1 1.0
1 2021-01-02 2 2.0
2 2021-01-03 4 4.0
3 2021-01-04 8 NaN
timestamp value difference
0 2021-01-01 1 1.0
1 2021-01-02 2 2.0
2 2021-01-03 4 4.0
3 2021-01-04 8 NaN
timestamp value difference
0 2021-01-01 1 NaN
1 2021-01-02 2 1.0
2 2021-01-03 4 2.0
3 2021-01-04 8 4.0
timestamp value difference
0 2021-01-01 1 NaN
1 2021-01-02 2 1.0
2 2021-01-03 4 2.0
3 2021-01-04 8 4.0
"""
Pandas替换数值
Pandas将所有小于0的值替换为0
import pandas as pd
# 创建一个包含负值的示例DataFrame
data = {'A': [1, 2, -1, 4], 'B': [5, -2, 7, 8]}
df = pd.DataFrame(data)
# 将所有小于0的值替换为0
# 找出所有大于0的值,将小于0的值置为Nan
df.where(df > 0, inplace = True)
df = df.fillna(0)
# 打印结果
print(df)
pandas根据初始范围修正推测的的范围,第一列为最小值,第二列为最大值,约束最新的值依旧在初始最大最小值间:
new_par_df.iloc[:,0] = par_range.where((par_range.iloc[:,0] > new_par_df.iloc[:,0]), new_par_df).iloc[:,0]
new_par_df.iloc[:,1] = par_range.where((par_range.iloc[:,1] < new_par_df.iloc[:,1]), new_par_df).iloc[:,1]
Pandas中的resample和rolling
小时数据转换为日数据,以下两种等价
label_data_d = label_data_h.resample("1D").sum() # 日值
等价为
label_data_r = label_data_h.rolling(window=24).sum()
label_data_d = label_data_r.loc[label_data_r.index.hour == 23]
参考文献
https://www.cnblogs.com/zhangyafei/p/10513893.html
时间序列与日期用法
时序数据处理