Pandas 時間序列處理


Pandas 時間序列處理

1 Python 的日期和時間處理

1.1 常用模塊

datetime time calendar

  • datetime,以毫秒形式存儲日期和時間
  • datime.timedelta,表示兩個 datetime 對象的時間差
  • datetime 模塊中包含的數據類型
類型 說明
date 以公歷形式存儲日歷日期(年、月、日)
time 將時間存儲為時、分、秒、毫秒
datetime 存儲日期和時間
timedelta 表示兩個 datetime 值之間的差(日、秒、毫秒)

1.2 字符串和 datetime 轉換

datetime -> str

  1. str(datetime_obj)
dt_obj = datetime(2019, 8, 8)
str_obj = str(dt_obj)
print(type(str_obj))
print(str_obj)

<class 'str'>
2019-08-08 00:00:00

  1. datetime.strftime()
str_obj2 = dt_obj.strftime('%d/%m/%Y')
print(str_obj2)

08/08/2019

str -> datetime

  1. datetime.strptime()
    需要指定時間表示的形式
dt_str = '2019-08-8'
dt_obj2 = datetime.strptime(dt_str, '%Y-%m-%d')
print(type(dt_obj2))
print(dt_obj2)

<class 'datetime.datetime'>
2019-08-08 00:00:00

  1. dateutil.parser.parse()
    可以解析大部分時間表示形式
from dateutil.parser import parse
dt_str2 = '8-08-2019'
dt_obj3 = parse(dt_str2)
print(type(dt_obj3))
print(dt_obj3)

<class 'datetime.datetime'>
2019-08-08 00:00:00

  1. pd.to_datetime()
    可以處理缺失值和空字符串

    具體看這

2 Pandas 的時間處理及操作

2.1 創建與基礎操作

基本類型,以時間戳為索引的 Series->Datetimelndex

指定 index 為 datetime 的 list

from datetime import datetime
import pandas as pd
import numpy as np

# 指定index為datetime的list
date_list = [datetime(2017, 2, 18), datetime(2017, 2, 19), 
             datetime(2017, 2, 25), datetime(2017, 2, 26), 
             datetime(2017, 3, 4), datetime(2017, 3, 5)]
time_s = pd.Series(np.random.randn(6), index=date_list)
print(time_s)
print(type(time_s.index))

2017-02-18 -0.230989
2017-02-19 -0.398082
2017-02-25 -0.309926
2017-02-26 -0.179672
2017-03-04 0.942698
2017-03-05 1.053092
dtype: float64
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>

索引

  • 索引位置
    print(time_s[0])

-0.230988627576

  • 索引值
    print(time_s[datetime(2017, 2, 18)])

-0.230988627576

  • 可以被解析的日期字符串
    print(time_s['20170218'])

-0.230988627576

  • 按“年份”、“月份”索引
    print(time_s['2017-2'])
2017-02-18   -0.230989
2017-02-19   -0.398082
2017-02-25   -0.309926
2017-02-26   -0.179672
dtype: float64
  • 切片操作
    print(time_s['2017-2-26':])
2017-02-26   -0.179672
2017-03-04    0.942698
2017-03-05    1.053092
dtype: float64

過濾

  • 過濾掉日期之前的
    time_s.truncate(before='2017-2-25')
2017-02-25   -0.309926
2017-02-26   -0.179672
2017-03-04    0.942698
2017-03-05    1.053092
dtype: float64
  • 過濾掉日期之后的
    time_s.truncate(after='2017-2-25')
2017-02-18   -0.230989
2017-02-19   -0.398082
2017-02-25   -0.309926
dtype: float64

pd.date_range()

功能:生成日期范圍

dates = pd.date_range('2017-02-18', # 起始日期
                      periods=5,    # 周期
                      freq='W-SAT') # 頻率
print(dates)
print(pd.Series(np.random.randn(5), index=dates))

DatetimeIndex(['2017-02-18', '2017-02-25', '2017-03-04', '2017-03-11',
'2017-03-18'],
dtype='datetime64[ns]', freq='W-SAT')
2017-02-18 -1.680280
2017-02-25 0.908664
2017-03-04 0.145318
2017-03-11 -2.940363
2017-03-18 0.152681
Freq: W-SAT, dtype: float64

  • 傳入開始、結束日期,默認生成的該時間段的時間點是按天計算的
    date_index = pd.date_range('2017/02/18', '2017/03/18')
  • 只傳入開始或結束日期,還需要傳入時間段
    print(pd.date_range(start='2017/02/18', periods=10, freq='4D'))
    print(pd.date_range(end='2017/03/18', periods=10))
  • 規范化時間戳
print(pd.date_range(start='2017/02/18 12:13:14', periods=10))
print(pd.date_range(start='2017/02/18 12:13:14', periods=10, normalize=True))

DatetimeIndex(['2017-02-18 12:13:14', '2017-02-19 12:13:14',
               '2017-02-20 12:13:14', '2017-02-21 12:13:14',
               '2017-02-22 12:13:14', '2017-02-23 12:13:14',
               '2017-02-24 12:13:14', '2017-02-25 12:13:14',
               '2017-02-26 12:13:14', '2017-02-27 12:13:14'],
              dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2017-02-18', '2017-02-19', '2017-02-20', '2017-02-21',
               '2017-02-22', '2017-02-23', '2017-02-24', '2017-02-25',
               '2017-02-26', '2017-02-27'],
              dtype='datetime64[ns]', freq='D')
頻率與偏移量
  • 頻率 Freq,由基礎頻率的倍數組成,基礎頻率包括:
    1.BM:business end of month,每個月最后一個工作日
    2.D:天,M:月等

  • 偏移量,每個基礎頻率對應一個偏移量
    1.偏移量通過加法連接
sum_offset = pd.tseries.offsets.Week(2) + pd.tseries.offsets.Hour(12)
print(sum_offset)

print(pd.date_range('2017/02/18', '2017/03/18', freq=sum_offset))
14 days 12:00:00
DatetimeIndex(['2017-02-18 00:00:00', '2017-03-04 12:00:00'], dtype='datetime64[ns]', freq='348H')
移動數據

沿時間軸將數據前移或后移,保持索引不變

ts = pd.Series(np.random.randn(5), index=pd.date_range('20170218', periods=5, freq='W-SAT'))
print(ts)
2017-02-18   -0.208622
2017-02-25    0.616093
2017-03-04   -0.424725
2017-03-11   -0.361475
2017-03-18    0.761274
Freq: W-SAT, dtype: float64

向后移動一位:print(ts.shift(1))

2017-02-18         NaN
2017-02-25   -0.208622
2017-03-04    0.616093
2017-03-11   -0.424725
2017-03-18   -0.361475
Freq: W-SAT, dtype: float64

pd.to_datetime()

功能:字符串轉成時間格式
import pandas as pd
s_obj = pd.Series(['2017/02/18', '2017/02/19', '2017-02-25', '2017-02-26'], name='course_time')
s_obj2 = pd.to_datetime(s_obj)
print(s_obj2)

0 2017-02-18
1 2017-02-19
2 2017-02-25
3 2017-02-26
Name: course_time, dtype: datetime64[ns]

# 處理缺失值
s_obj3 = pd.Series(['2017/02/18', '2017/02/19', '2017-02-25', '2017-02-26'] + [None], 
                   name='course_time')
print(s_obj3)
0    2017/02/18
1    2017/02/19
2    2017-02-25
3    2017-02-26
4          None
Name: course_time, dtype: object

時間周期計算

  • Period 類,通過字符串或整數及基礎頻率構造
  • Period 對象可進行數學運算,但要保證具有相同的基礎頻率
  • period_range,創建指定規則的時間周期范圍,生成 Periodlndex 索引,可用於創建 Series 或 DataFrame
  • 時間周期的頻率轉換,asfreq
    • 如:年度周期->月度周期
  • 按季度計算時間周期頻率

2.2 時間數據重采樣

重采樣(resampling)

  • 將時間序列從一個頻率轉換到另一個頻率的過程,需要聚合
  • 高頻率->低頻率,downsampling,相反為 upsampling
  • pandas 中的 resample 方法實現重采樣
    • 產生 Resampler 對象
    • reample(freq).sum0,resampe(freq).mean).…
import pandas as pd
import numpy as np

date_rng = pd.date_range('20170101', periods=100, freq='D')
ser_obj = pd.Series(range(len(date_rng)), index=date_rng)

# 統計每個月的數據總和
resample_month_sum = ser_obj.resample('M').sum()
# 統計每個月的數據平均
resample_month_mean = ser_obj.resample('M').mean()

print('按月求和:', resample_month_sum)
print('按月求均值:', resample_month_mean)
按月求和: 2017-01-31     465
2017-02-28    1246
2017-03-31    2294
2017-04-30     945
Freq: M, dtype: int32
按月求均值: 2017-01-31    15.0
2017-02-28    44.5
2017-03-31    74.0
2017-04-30    94.5
Freq: M, dtype: float64

降采樣(downsampling)

  • 將數據聚合到規整的低頻率
  • OHLC重采樣,open,high,low,close
# 將數據聚合到5天的頻率
five_day_sum_sample = ser_obj.resample('5D').sum()
five_day_mean_sample = ser_obj.resample('5D').mean()
five_day_ohlc_sample = ser_obj.resample('5D').ohlc()
  • 使用 groupby 降采樣
    使用函數對其進行分組操作
    ser_obj.groupby(lambda x: x.month).sum()
    ser_obj.groupby(lambda x: x.weekday).sum()

升采樣(upsampling)

  • 將數據從低頻轉到高頻,需要插值,否則為 NaN (直接重采樣會產生空值)
  • 常用的插值方法
  1. ffill(limit),空值取前面的值填充,limit 為填充個數
    df.resample('D').ffill(2)
  2. bfill(limit),空值取后面的值填充
    df.resample('D').bfill()
  3. fillna(fill')或 fllna(‘bfill)
    df.resample('D').fillna('ffill')
  4. interpolate,根據插值算法補全數據
    線性算法:df.resample('D').interpolate('linear')
    具體可以參考:pandas.core.resample.Resampler.interpolate

2.3 滑動窗口

  • 在時間窗口上計算各種統計函數

  • 窗口函數(window functions)
  1. 滾動統計(rolling)
    obj.rolling().func
import pandas as pd
import numpy as np

ser_obj = pd.Series(np.random.randn(1000), 
                    index=pd.date_range('20170101', periods=1000))
ser_obj = ser_obj.cumsum()
r_obj = ser_obj.rolling(window=5)
print(r_obj)

Rolling [window=5,center=False,axis=0]

  1. window
    窗口大小
  2. center
    窗口是否居中統計

設置居中:

# 畫圖查看
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(15, 5))

ser_obj.plot(style='r--')
ser_obj.rolling(window=10, center=True).mean().plot(style='b')

不設置居中:
ser_obj.rolling(window=10, center=False).mean().plot(style='b')


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM