【Pandas】Pandas时间序列操作笔记

本文介绍了Pandas处理时间序列数据的方法,包括时间戳的使用、时区转换、CSV时间索引解析以及在SQLite中的读取和处理缺失值。重点讨论了如何在不同时区之间转换时间戳,以及如何利用pandas的resample和rolling函数进行时间序列的重采样和滚动窗口计算。
摘要由CSDN通过智能技术生成

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
时间序列与日期用法
时序数据处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KmBase

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值