1. 程式人生 > >python之時間序列

python之時間序列

不管在哪個領域中(如金融學、經濟學、生態學、神經科學、物理學等),時間序列(time series)資料都是一種重要的結構化資料形式。在多個時間點觀察或測量到的任何事物都可以形成一段時間序列。很多時間序列都是固定頻率的,也就是說,資料點是根據某種規律定期出現的(比如每15秒、每5分鐘、每個月出現一次)。時間序列也可以是不定期的。時間序列資料的意義取決於具體的應用場景,主要有以下幾種:

  • 時間戳(timestamp),特定的時刻。
  • 固定時期(period),如2018年4月或2017全年。可以看做時間間隔的特例。
  • 時間間隔,由起始和結束時間戳表示。
  • 實驗或過程時間,每個時間點都是相對於特定起始時間的一個度量。

日期和時間資料型別及工具

python標準庫包含用於日期(date)和時間(time)資料的資料型別,而且還有日曆方面的功能。主要用到的模組:datetime、time以及calendar模組。

程式碼示例:

from datetime import datetime
from datetime import timedelta
#毫秒形式儲存日期和時間
#datetime(year, month, day, hour, minute, second, microsecond)
now = datetime.now()  #now=datetime.datetime(2018, 4, 10, 16, 56, 29, 739397)
#datetime.timedelta表示兩個datetime物件之間的時間差
#timedelta(days,seconds)
delta = datetime(2018, 4, 10) - datetime(2017, 7, 1, 1, 20)
#delta=  datetime.timedelta(282, 81600)
#給datetime物件加/減上timedelta
start = datetime(2018, 1, 1) 
start + timedelta(12)     #result:datetime.datetime(2018, 1, 13, 0, 0)
start - 2 * timedelta(12)  #result:datetime.datetime(2017, 12, 8, 0, 0)

字串與datatime之間的相互轉換

  • 利用str或strftime方法,可以將datetime物件和pandas的Timestamp物件被格式化為字串;
  • datetime.strptime也可以用這些格式化編碼將字串轉換為日期;
  • dateutil包中parser.parse方法進行日期解析,可以解析幾乎所有日期表現形式。
  • pandas.to_datetime可以解析多種不同的日期表現形式

datetime中格式定義(英語系統下):


程式碼示例:

from dateutil.parser import parse
import pandas as pd
#字串與datetime物件的轉換
#datetime物件轉換為字串
stamp = datetime(2018, 1, 1)
#第一種str方法
str(stamp)              #'2018-01-01 00:00:00'
#第二中strftime
stamp.strftime('%Y-%m-%d')
#字串物件轉換為datetime,利用strptime
#strptime通過已知格式進行日期解析的最佳方法
value = '2018-01-01'     #'2018-01-01'
datetime.strptime(value, '%Y-%m-%d')

#parser.parse方法進行日期解析,可以解析幾乎所有日期表現形式。
parse('2018-01-01')                #datetime.datetime(2018, 1, 1, 0, 0)
parse('Jan 01, 2018 6:45 PM')      #datetime.datetime(2018, 1, 1, 18, 45)
#parse解析字串時,預設月在前,日在後
parse('6/12/2011')   # datetime.datetime(2011, 6, 12, 0, 0)
#因此,對於日在前,月在後的,可以設定 dayfirst=True
parse('6/12/2011', dayfirst=True)  #datetime.datetime(2011, 12, 6, 0, 0)

#to_datetime可以解析多種不同的日期表現形式
datestrs = ['2018-01-01 12:00:00', '2018-02-22 00:00:00']
pd.to_datetime(datestrs)
#DatetimeIndex(['2018-01-01 12:00:00', '2018-02-22 00:00:00'], dtype='datetime64[ns]', freq=None)
#還可以處理預設值(空字串或None)
idx = pd.to_datetime(datestrs + [None])
#idx=DatetimeIndex(['2018-01-01 12:00:00', '2018-02-22 00:00:00', 'NaT'], dtype='datetime64[ns]', freq=None)
#注意:日期中的預設值是NaT(Not a Time)
pd.isnull(idx)   #array([False, False,  True], dtype=bool)

二、世界序列基礎

pandas最基礎的時間序列型別就是以時間戳(通常以python字串或datetime物件表示)為索引的Series。

主要兩部分:

  • 索引、選取、子集構造;
  • 帶重複索引的時間序列。
程式碼示例:
#索引、選取、子集構造
#索引
#方法1,傳入一個Timestamp物件
stamp = ts.index[0]   #stamp=Timestamp('2018-01-02 00:00:00')
ts[stamp]             # -0.10607355595045509
#傳入一個可以被解釋為日期的字串
ts['1/10/2018']      #-1.5461476964186704
ts['20180110']       #-1.5461476964186704
#切片
#對於較長的時間序列,通過傳入“年”、“年月”即可輕鬆選取資料切片
longer_ts = pd.Series(np.random.randn(1000),
                      index=pd.date_range('1/1/2018', periods=1000))
longer_ts['2018']      
longer_ts['2018-03']
#通過日期進行切片的方式只對規則的Series有效
ts[datetime(2018, 1, 10):]
"""ts:                            ts[datetime(2018, 1, 10):]:
2018-01-02   -0.106074              2018-01-10   -1.546148
2018-01-03    0.100822              2018-01-13    0.141358
2018-01-06   -0.894717              dtype: float64
2018-01-08   -0.498678
2018-01-10   -1.546148
2018-01-13    0.141358
dtype: float64
"""
#時間序列大部分按時間先後順序排列,可以使用不存在該時間序列的時間戳來進行切片(即:查詢範圍)
ts['1/5/2018':'1/15/2018'] 
"""
2018-01-06   -0.894717
2018-01-08   -0.498678
2018-01-10   -1.546148
2018-01-13    0.141358
dtype: float64
"""
#擷取兩個日期之間的TimeSeries
#擷取2018-1-9之前的徐磊
ts.truncate(after='1/9/2018')
"""
2018-01-02   -0.106074
2018-01-03    0.100822
2018-01-06   -0.894717
2018-01-08   -0.498678
dtype: float64
"""
#對於DataFrame物件同樣有用,時間點只取週三(freq='W-WED')
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',
                                'New York', 'Ohio'])
long_df.loc['3-2018']
"""
            Colorado     Texas  New York      Ohio
2018-03-07  0.903078 -0.931066  0.213840  0.169752
2018-03-14  1.874872 -0.682288 -0.820822 -0.451576
2018-03-21  0.381608 -0.493432  0.284216  0.353538
2018-03-28 -0.412199  0.102380 -0.363941 -1.693375
"""
#帶重複索引的時間序列
dates = pd.DatetimeIndex(['1/1/2018', '1/2/2018', '1/2/2018',
                          '1/2/2018', '1/3/2018'])
dup_ts = pd.Series(np.arange(5), index=dates)
"""dup_ts=
2018-01-01    0
2018-01-02    1
2018-01-02    2
2018-01-02    3
2018-01-03    4
dtype: int32
"""
#利用is_unique屬性查詢是否唯一
dup_ts.index.is_unique     # False
#索引時,如果索引重複,則產生標量值,反之,則產生切片
dup_ts['1/3/2018']  # 索引不重複,4
dup_ts['1/2/2018']  # 索引重複的
"""
2018-01-02    1
2018-01-02    2
2018-01-02    3
dtype: int32
"""
#對非唯一時間戳進行聚合,並傳入level=0(索引的唯一一層!)
grouped = dup_ts.groupby(level=0)
grouped.mean()
grouped.count()
"""
grouped.mean():              grouped.count():
2018-01-01    0              2018-01-01    1
2018-01-02    2              2018-01-02    3
2018-01-03    4              2018-01-03    1
"""

附:時間序列的基礎頻率一覽表: