【Pandas】Pandas的時間與日期
注意:重要且關鍵章節已標星
目錄
事實證明,熊貓作為處理時間序列資料的工具非常成功,特別是在財務資料分析領域。使用NumPy datetime64
和timedelta64
dtypes,我們整合了其他Python庫中的大量功能,scikits.timeseries
在處理時間序列資料時,我們會經常尋求:
- 生成固定頻率日期和時間跨度的序列
- 使時間序列符合或轉換為特定頻率
- 根據各種非標準時間增量計算“相對”日期(例如,在一年的最後一個工作日之前的5個工作日),或向前或向後“滾動”日期
pandas提供了一套相對緊湊且獨立的工具,用於執行上述任務。
建立一系列日期:
In [1]: rng = pd.date_range('1/1/2011', periods=72, freq='H') In [2]: rng[:5] Out[2]: DatetimeIndex(['2011-01-01 00:00:00', '2011-01-01 01:00:00', '2011-01-01 02:00:00', '2011-01-01 03:00:00', '2011-01-01 04:00:00'], dtype='datetime64[ns]', freq='H')
帶有日期的索引pandas物件:
In [3]: ts = pd.Series(np.random.randn(len(rng)), index=rng)
In [4]: ts.head()
Out[4]:
2011-01-01 00:00:00 0.469112
2011-01-01 01:00:00 -0.282863
2011-01-01 02:00:00 -1.509059
2011-01-01 03:00:00 -1.135632
2011-01-01 04:00:00 1.212112
Freq: H, dtype: float64
改變頻率和填補空白:
# 到45分鐘的頻率和前向填充 In [5]: converted = ts.asfreq('45Min', method='pad') In [6]: converted.head() Out[6]: 2011-01-01 00:00:00 0.469112 2011-01-01 00:45:00 0.469112 2011-01-01 01:30:00 -0.282863 2011-01-01 02:15:00 -1.509059 2011-01-01 03:00:00 -1.135632 Freq: 45T, dtype: float64
將系列重新取樣到每日頻率:
# 日平均
In [7]: ts.resample('D').mean()
Out[7]:
2011-01-01 -0.319569
2011-01-02 -0.337703
2011-01-03 0.117258
Freq: D, dtype: float64
概述
下表顯示了pandas可以處理的與時間相關的類的型別以及如何建立它們。
類 | 備註 | 如何創造 |
---|---|---|
Timestamp |
表示單個時間戳 | to_datetime , Timestamp |
DatetimeIndex |
指數 Timestamp |
to_datetime ,date_range ,bdate_range ,DatetimeIndex |
Period |
表示單個時間跨度 | Period |
PeriodIndex |
指數 Period |
period_range , PeriodIndex |
時間戳與時間跨度
帶時間戳的資料是將值與時間點相關聯的最基本型別的時間序列資料。對於pandas物件,它意味著使用時間點。
In [8]: pd.Timestamp(datetime(2012, 5, 1))
Out[8]: Timestamp('2012-05-01 00:00:00')
In [9]: pd.Timestamp('2012-05-01')
Out[9]: Timestamp('2012-05-01 00:00:00')
In [10]: pd.Timestamp(2012, 5, 1)
Out[10]: Timestamp('2012-05-01 00:00:00')
但是,在許多情況下,將變數變數與時間跨度相關聯更為自然。表示的範圍Period
可以顯式指定,也可以從日期時間字串格式推斷。
例如:
In [11]: pd.Period('2011-01')
Out[11]: Period('2011-01', 'M')
In [12]: pd.Period('2012-05', freq='D')
Out[12]: Period('2012-05-01', 'D')
In [13]: dates = [pd.Timestamp('2012-05-01'), pd.Timestamp('2012-05-02'), pd.Timestamp('2012-05-03')]
In [14]: ts = pd.Series(np.random.randn(3), dates)
In [15]: type(ts.index)
Out[15]: pandas.core.indexes.datetimes.DatetimeIndex
In [16]: ts.index
Out[16]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
In [17]: ts
Out[17]:
2012-05-01 -0.410001
2012-05-02 -0.078638
2012-05-03 0.545952
dtype: float64
In [18]: periods = [pd.Period('2012-01'), pd.Period('2012-02'), pd.Period('2012-03')]
In [19]: ts = pd.Series(np.random.randn(3), periods)
In [20]: type(ts.index)
Out[20]: pandas.core.indexes.period.PeriodIndex
In [21]: ts.index
Out[21]: PeriodIndex(['2012-01', '2012-02', '2012-03'], dtype='period[M]', freq='M')
In [22]: ts
Out[22]:
2012-01 -1.219217
2012-02 -1.226825
2012-03 0.769804
Freq: M, dtype: float64
pandas允許您捕獲兩個表示並在它們之間進行轉換。在引擎蓋下,pandas表示使用例項的時間戳的例項Timestamp
和時間戳的時間戳 DatetimeIndex
。對於常規時間跨度,pandas使用Period
物件作為標量值和PeriodIndex
跨度序列。在未來的版本中,對具有任意起點和終點的不規則間隔的更好支援將會出現。
轉換為時間戳
要轉換Series
類似日期的物件或類似列表的物件,例如字串,紀元或混合,您可以使用該to_datetime
函式。當傳遞a時Series
,它返回一個Series
(具有相同的索引),而類似列表的轉換為DatetimeIndex
:
In [23]: pd.to_datetime(pd.Series(['Jul 31, 2009', '2010-01-10', None]))
Out[23]:
0 2009-07-31
1 2010-01-10
2 NaT
dtype: datetime64[ns]
In [24]: pd.to_datetime(['2005/11/23', '2010.12.31'])
Out[24]: DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)
如果您使用從第一天開始的日期(即歐洲風格),您可以傳遞dayfirst
旗幟:
In [25]: pd.to_datetime(['04-01-2012 10:00'], dayfirst=True)
Out[25]: DatetimeIndex(['2012-01-04 10:00:00'], dtype='datetime64[ns]', freq=None)
In [26]: pd.to_datetime(['14-01-2012', '01-14-2012'], dayfirst=True)
Out[26]: DatetimeIndex(['2012-01-14', '2012-01-14'], dtype='datetime64[ns]', freq=None)
警告:您在上面的示例中看到
dayfirst
的並不嚴格,因此如果無法在第一天解析日期,則會將其解析為dayfirst
False。
如果傳遞單個字串to_datetime
,則返回單個字串Timestamp
。 Timestamp
也可以接受字串輸入,但是它不接受像dayfirst
或format
那樣的字串解析選項,所以to_datetime
如果需要這些選項則使用。
In [27]: pd.to_datetime('2010/11/12')
Out[27]: Timestamp('2010-11-12 00:00:00')
In [28]: pd.Timestamp('2010/11/12')
Out[28]: Timestamp('2010-11-12 00:00:00')
提供格式引數(指定時間格式)*
除了所需的日期時間字串之外,format
還可以傳遞引數以確保特定的解析。這也可能大大加快轉換速度。
In [29]: pd.to_datetime('2010/11/12', format='%Y/%m/%d')
Out[29]: Timestamp('2010-11-12 00:00:00')
In [30]: pd.to_datetime('12-11-2010 00:00', format='%d-%m-%Y %H:%M')
Out[30]: Timestamp('2010-11-12 00:00:00')
有關指定format
選項時可用選項的更多資訊,請參閱Python datetime文件。
從多個DataFrame列組裝日期時間
您也可以通過一個DataFrame
整數或字串列組裝成Series
的Timestamps
。
In [31]: df = pd.DataFrame({'year': [2015, 2016],
....: 'month': [2, 3],
....: 'day': [4, 5],
....: 'hour': [2, 3]})
....:
In [32]: pd.to_datetime(df)
Out[32]:
0 2015-02-04 02:00:00
1 2016-03-05 03:00:00
dtype: datetime64[ns]
您只能傳遞需要組裝的列。
In [33]: pd.to_datetime(df[['year', 'month', 'day']])
Out[33]:
0 2015-02-04
1 2016-03-05
dtype: datetime64[ns]
pd.to_datetime
在列名中查詢datetime元件的標準名稱,包括:
- 要求:
year
,month
,day
- 可選:
hour
,minute
,second
,millisecond
,microsecond
,nanosecond
無效資料
預設行為errors='raise'
是在不可解析時引發:
In [2]: pd.to_datetime(['2009/07/31', 'asd'], errors='raise')
ValueError: Unknown string format
傳遞errors='ignore'
以在不可解析時返回原始輸入:
In [34]: pd.to_datetime(['2009/07/31', 'asd'], errors='ignore')
Out[34]: array(['2009/07/31', 'asd'], dtype=object)
傳遞errors='coerce'
將不可解析的資料轉換為NaT
(不是時間):
In [35]: pd.to_datetime(['2009/07/31', 'asd'], errors='coerce')
Out[35]: DatetimeIndex(['2009-07-31', 'NaT'], dtype='datetime64[ns]', freq=None)
紀元時間戳
pandas支援將整數或浮點時間轉換為Timestamp
和 DatetimeIndex
。預設單位是納秒,因為這是Timestamp
物件在內部儲存的方式。但是,時期通常儲存在另一個unit
可以指定的時期。這些是從origin
引數指定的起始點計算的 。
In [36]: pd.to_datetime([1349720105, 1349806505, 1349892905,
....: 1349979305, 1350065705], unit='s')
....:
Out[36]:
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
'2012-10-10 18:15:05', '2012-10-11 18:15:05',
'2012-10-12 18:15:05'],
dtype='datetime64[ns]', freq=None)
In [37]: pd.to_datetime([1349720105100, 1349720105200, 1349720105300,
....: 1349720105400, 1349720105500 ], unit='ms')
....:
Out[37]:
DatetimeIndex(['2012-10-08 18:15:05.100000', '2012-10-08 18:15:05.200000',
'2012-10-08 18:15:05.300000', '2012-10-08 18:15:05.400000',
'2012-10-08 18:15:05.500000'],
dtype='datetime64[ns]', freq=None)
注意:大紀元時間將四捨五入到最接近的納秒。
警告:
浮動紀元時間的轉換可能導致不準確和意外的結果。 Python浮點數的十進位制精度約為15位。從浮動到高精度的轉換過程中的舍入
Timestamp
是不可避免的。實現精確精度的唯一方法是使用固定寬度型別(例如int64)。In [38]: pd.to_datetime([1490195805.433, 1490195805.433502912], unit='s') Out[38]: DatetimeIndex(['2017-03-22 15:16:45.433000088', '2017-03-22 15:16:45.433502913'], dtype='datetime64[ns]', freq=None) In [39]: pd.to_datetime(1490195805433502912, unit='ns') Out[39]: Timestamp('2017-03-22 15:16:45.433502912')
從時間戳到紀元
要從上面反轉操作,即從a轉換Timestamp
為'unix'時代:
In [40]: stamps = pd.date_range('2012-10-08 18:15:05', periods=4, freq='D')
In [41]: stamps
Out[41]:
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
'2012-10-10 18:15:05', '2012-10-11 18:15:05'],
dtype='datetime64[ns]', freq='D')
我們減去時期(UTC時間1970年1月1日午夜),然後除以“單位”(1秒)。
In [42]: (stamps - pd.Timestamp("1970-01-01")) // pd.Timedelta('1s')
Out[42]: Int64Index([1349720105, 1349806505, 1349892905, 1349979305], dtype='int64')
使用origin
引數
使用該origin
引數,可以指定建立a的替代起點DatetimeIndex
。例如,要使用1960-01-01作為開始日期:
In [43]: pd.to_datetime([1, 2, 3], unit='D', origin=pd.Timestamp('1960-01-01'))
Out[43]: DatetimeIndex(['1960-01-02', '1960-01-03', '1960-01-04'], dtype='datetime64[ns]', freq=None)
預設設定為origin='unix'
,預設為。俗稱'unix epoch'或POSIX時間。1970-01-01 00:00:00
In [44]: pd.to_datetime([1, 2, 3], unit='D')
Out[44]: DatetimeIndex(['1970-01-02', '1970-01-03', '1970-01-04'], dtype='datetime64[ns]', freq=None)
生成時間戳範圍
要生成帶時間戳的索引,可以使用DatetimeIndex
或 Index
建構函式並傳入datetime物件列表:
In [45]: dates = [datetime(2012, 5, 1), datetime(2012, 5, 2), datetime(2012, 5, 3)]
# Note the frequency information
In [46]: index = pd.DatetimeIndex(dates)
In [47]: index
Out[47]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
# Automatically converted to DatetimeIndex
In [48]: index = pd.Index(dates)
In [49]: index
Out[49]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
在實踐中,這變得非常麻煩,因為我們經常需要具有大量時間戳的非常長的索引。如果我們需要常規頻率的時間戳,我們可以使用date_range()
和bdate_range()
函式來建立一個DatetimeIndex
。對於預設頻率date_range
為一個 日曆日,而預設bdate_range
是工作日:
In [50]: start = datetime(2011, 1, 1)
In [51]: end = datetime(2012, 1, 1)
In [52]: index = pd.date_range(start, end)
In [53]: index
Out[53]:
DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04',
'2011-01-05', '2011-01-06', '2011-01-07', '2011-01-08',
'2011-01-09', '2011-01-10',
...
'2011-12-23', '2011-12-24', '2011-12-25', '2011-12-26',
'2011-12-27', '2011-12-28', '2011-12-29', '2011-12-30',
'2011-12-31', '2012-01-01'],
dtype='datetime64[ns]', length=366, freq='D')
In [54]: index = pd.bdate_range(start, end)
In [55]: index
Out[55]:
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
'2011-01-07', '2011-01-10', '2011-01-11', '2011-01-12',
'2011-01-13', '2011-01-14',
...
'2011-12-19', '2011-12-20', '2011-12-21', '2011-12-22',
'2011-12-23', '2011-12-26', '2011-12-27', '2011-12-28',
'2011-12-29', '2011-12-30'],
dtype='datetime64[ns]', length=260, freq='B')
方便功能date_range
,bdate_range
可以使用各種頻率別名:
In [56]: pd.date_range(start, periods=1000, freq='M')
Out[56]:
DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-30',
'2011-05-31', '2011-06-30', '2011-07-31', '2011-08-31',
'2011-09-30', '2011-10-31',
...
'2093-07-31', '2093-08-31', '2093-09-30', '2093-10-31',
'2093-11-30', '2093-12-31', '2094-01-31', '2094-02-28',
'2094-03-31', '2094-04-30'],
dtype='datetime64[ns]', length=1000, freq='M')
In [57]: pd.bdate_range(start, periods=250, freq='BQS')
Out[57]:
DatetimeIndex(['2011-01-03', '2011-04-01', '2011-07-01', '2011-10-03',
'2012-01-02', '2012-04-02', '2012-07-02', '2012-10-01',
'2013-01-01', '2013-04-01',
...
'2071-01-01', '2071-04-01', '2071-07-01', '2071-10-01',
'2072-01-01', '2072-04-01', '2072-07-01', '2072-10-03',
'2073-01-02', '2073-04-03'],
dtype='datetime64[ns]', length=250, freq='BQS-JAN')
date_range
並且bdate_range
可以很容易地使用的引數的各種組合等生成日期的範圍start
,end
,periods
,和freq
。開始日期和結束日期是嚴格包含的,因此不會生成指定日期之外的日期:
In [58]: pd.date_range(start, end, freq='BM')
Out[58]:
DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-29',
'2011-05-31', '2011-06-30', '2011-07-29', '2011-08-31',
'2011-09-30', '2011-10-31', '2011-11-30', '2011-12-30'],
dtype='datetime64[ns]', freq='BM')
In [59]: pd.date_range(start, end, freq='W')
Out[59]:
DatetimeIndex(['2011-01-02', '2011-01-09', '2011-01-16', '2011-01-23',
'2011-01-30', '2011-02-06', '2011-02-13', '2011-02-20',
'2011-02-27', '2011-03-06', '2011-03-13', '2011-03-20',
'2011-03-27', '2011-04-03', '2011-04-10', '2011-04-17',
'2011-04-24', '2011-05-01', '2011-05-08', '2011-05-15',
'2011-05-22', '2011-05-29', '2011-06-05', '2011-06-12',
'2011-06-19', '2011-06-26', '2011-07-03', '2011-07-10',
'2011-07-17', '2011-07-24', '2011-07-31', '2011-08-07',
'2011-08-14', '2011-08-21', '2011-08-28', '2011-09-04',
'2011-09-11', '2011-09-18', '2011-09-25', '2011-10-02',
'2011-10-09', '2011-10-16', '2011-10-23', '2011-10-30',
'2011-11-06', '2011-11-13', '2011-11-20', '2011-11-27',
'2011-12-04', '2011-12-11', '2011-12-18', '2011-12-25',
'2012-01-01'],
dtype='datetime64[ns]', freq='W-SUN')
In [60]: pd.bdate_range(end=end, periods=20)
Out[60]:
DatetimeIndex(['2011-12-05', '2011-12-06', '2011-12-07', '2011-12-08',
'2011-12-09', '2011-12-12', '2011-12-13', '2011-12-14',
'2011-12-15', '2011-12-16', '2011-12-19', '2011-12-20',
'2011-12-21', '2011-12-22', '2011-12-23', '2011-12-26',
'2011-12-27', '2011-12-28', '2011-12-29', '2011-12-30'],
dtype='datetime64[ns]', freq='B')
In [61]: pd.bdate_range(start=start, periods=20)
Out[61]:
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
'2011-01-07', '2011-01-10', '2011-01-11', '2011-01-12',
'2011-01-13', '2011-01-14', '2011-01-17', '2011-01-18',
'2011-01-19', '2011-01-20', '2011-01-21', '2011-01-24',
'2011-01-25', '2011-01-26', '2011-01-27', '2011-01-28'],
dtype='datetime64[ns]', freq='B')
版本0.23.0中的新功能。
指定start
,end
和periods
將生成一系列均勻間隔的日期,start
從而end
包含,結果中包含periods
多個元素DatetimeIndex
:
In [62]: pd.date_range('2018-01-01', '2018-01-05', periods=5)
Out[62]:
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
'2018-01-05'],
dtype='datetime64[ns]', freq=None)
In [63]: pd.date_range('2018-01-01', '2018-01-05', periods=10)
Out[63]:
DatetimeIndex(['2018-01-01 00:00:00', '2018-01-01 10:40:00',
'2018-01-01 21:20:00', '2018-01-02 08:00:00',
'2018-01-02 18:40:00', '2018-01-03 05:20:00',
'2018-01-03 16:00:00', '2018-01-04 02:40:00',
'2018-01-04 13:20:00', '2018-01-05 00:00:00'],
dtype='datetime64[ns]', freq=None)
自定義頻率範圍
警告:此功能最初是獨佔的
cdate_range
,從版本0.21.0開始不贊成使用bdate_range
。請注意,cdate_range
僅在自定義工作日“C”作為頻率字串傳遞時才使用weekmask
和holidays
引數。支援已經擴充套件,bdate_range
可以使用任何自定義頻率字串。
版本0.21.0中的新功能。
bdate_range
還可以使用weekmask
和holidays
引數生成一系列自定義頻率日期。僅在傳遞自定義頻率字串時才使用這些引數。
In [64]: weekmask = 'Mon Wed Fri'
In [65]: holidays = [datetime(2011, 1, 5), datetime(2011, 3, 14)]
In [66]: pd.bdate_range(start, end, freq='C', weekmask=weekmask, holidays=holidays)
Out[66]:
DatetimeIndex(['2011-01-03', '2011-01-07', '2011-01-10', '2011-01-12',
'2011-01-14', '2011-01-17', '2011-01-19', '2011-01-21',
'2011-01-24', '2011-01-26',
...
'2011-12-09', '2011-12-12', '2011-12-14', '2011-12-16',
'2011-12-19', '2011-12-21', '2011-12-23', '2011-12-26',
'2011-12-28', '2011-12-30'],
dtype='datetime64[ns]', length=154, freq='C')
In [67]: pd.bdate_range(start, end, freq='CBMS', weekmask=weekmask)
Out[67]:
DatetimeIndex(['2011-01-03', '2011-02-02', '2011-03-02', '2011-04-01',
'2011-05-02', '2011-06-01', '2011-07-01', '2011-08-01',
'2011-09-02', '2011-10-03', '2011-11-02', '2011-12-02'],
dtype='datetime64[ns]', freq='CBMS')
時間戳限制
由於pandas表示以納秒解析度表示的時間戳,因此使用64位整數表示的時間跨度限制為大約584年:
In [68]: pd.Timestamp.min
Out[68]: Timestamp('1677-09-21 00:12:43.145225')
In [69]: pd.Timestamp.max
Out[69]: Timestamp('2262-04-11 23:47:16.854775807')
索引
其中一個主要用途DatetimeIndex
是作為pandas物件的索引。本DatetimeIndex
類包含許多時間序列相關的優化:
- 各種偏移的大範圍日期被預先計算並快取在引擎蓋下,以便非常快地生成後續日期範圍(只需抓取一個切片)。
- 使用pandas物件上的
shift
andtshift
方法快速移動。DatetimeIndex
具有相同頻率的重疊物件的聯合非常快(對於快速資料對齊很重要)。- 通過效能,如快速訪問日期欄位
year
,month
等等。- 正則化功能
snap
和非常快速的asof
邏輯。
DatetimeIndex
物件具有常規Index
物件的所有基本功能,以及高階時間序列特定方法的大雜燴,便於頻率處理。
注意:雖然pandas不會強制您使用已排序的日期索引,但如果日期未排序,則某些方法可能會出現意外或不正確的行為。
DatetimeIndex
可以像常規索引一樣使用,並提供所有智慧功能,如選擇,切片等。
In [70]: rng = pd.date_range(start, end, freq='BM')
In [71]: ts = pd.Series(np.random.randn(len(rng)), index=rng)
In [72]: ts.index
Out[72]:
DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-29',
'2011-05-31', '2011-06-30', '2011-07-29', '2011-08-31',
'2011-09-30', '2011-10-31', '2011-11-30', '2011-12-30'],
dtype='datetime64[ns]', freq='BM')
In [73]: ts[:5].index
Out[73]:
DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-29',
'2011-05-31'],
dtype='datetime64[ns]', freq='BM')
In [74]: ts[::2].index
Out[74]:
DatetimeIndex(['2011-01-31', '2011-03-31', '2011-05-31', '2011-07-29',
'2011-09-30', '2011-11-30'],
dtype='datetime64[ns]', freq='2BM')
部分字串索引
解析為時間戳的日期和字串可以作為索引引數傳遞:
In [75]: ts['1/31/2011']
Out[75]: -1.2812473076599531
In [76]: ts[datetime(2011, 12, 25):]
Out[76]:
2011-12-30 0.687738
Freq: BM, dtype: float64
In [77]: ts['10/31/2011':'12/31/2011']
Out[77]:
2011-10-31 0.149748
2011-11-30 -0.732339
2011-12-30 0.687738
Freq: BM, dtype: float64
為了方便訪問更長的時間序列,您還可以將年份或年份和月份作為字串傳遞:
In [78]: ts['2011']
Out[78]:
2011-01-31 -1.281247
2011-02-28 -0.727707
2011-03-31 -0.121306
2011-04-29 -0.097883
2011-05-31 0.695775
2011-06-30 0.341734
2011-07-29 0.959726
2011-08-31 -1.110336
2011-09-30 -0.619976
2011-10-31 0.149748
2011-11-30 -0.732339
2011-12-30 0.687738
Freq: BM, dtype: float64
In [79]: ts['2011-6']
Out[79]:
2011-06-30 0.341734
Freq: BM, dtype: float64
這種型別的切片將在一個工作DataFrame
用DatetimeIndex
為好。由於部分字串選擇是標籤切片的一種形式,因此將包括端點。這將包括在包含日期的匹配時間:
In [80]: dft = pd.DataFrame(randn(100000,1),
....: columns=['A'],
....: index=pd.date_range('20130101',periods=100000,freq='T'))
....:
In [81]: dft
Out[81]:
A
2013-01-01 00:00:00 0.176444
2013-01-01 00:01:00 0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00 0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
... ...
2013-03-11 10:33:00 -0.293083
2013-03-11 10:34:00 -0.059881
2013-03-11 10:35:00 1.252450
2013-03-11 10:36:00 0.046611
2013-03-11 10:37:00 0.059478
2013-03-11 10:38:00 -0.286539
2013-03-11 10:39:00 0.841669
[100000 rows x 1 columns]
In [82]: dft['2013']
Out[82]:
A
2013-01-01 00:00:00 0.176444
2013-01-01 00:01:00 0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00 0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
... ...
2013-03-11 10:33:00 -0.293083
2013-03-11 10:34:00 -0.059881
2013-03-11 10:35:00 1.252450
2013-03-11 10:36:00 0.046611
2013-03-11 10:37:00 0.059478
2013-03-11 10:38:00 -0.286539
2013-03-11 10:39:00 0.841669
[100000 rows x 1 columns]
這是在本月的第一次開始,包括該月的最後日期和時間:
In [83]: dft['2013-1':'2013-2']
Out[83]:
A
2013-01-01 00:00:00 0.176444
2013-01-01 00:01:00 0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00 0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
... ...
2013-02-28 23:53:00 0.103114
2013-02-28 23:54:00 -1.303422
2013-02-28 23:55:00 0.451943
2013-02-28 23:56:00 0.220534
2013-02-28 23:57:00 -1.624220
2013-02-28 23:58:00 0.093915
2013-02-28 23:59:00 -1.087454
[84960 rows x 1 columns]
這指定了包含最後一天所有時間的停止時間:
In [84]: dft['2013-1':'2013-2-28']
Out[84]:
A
2013-01-01 00:00:00 0.176444
2013-01-01 00:01:00 0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00 0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
... ...
2013-02-28 23:53:00 0.103114
2013-02-28 23:54:00 -1.303422
2013-02-28 23:55:00 0.451943
2013-02-28 23:56:00 0.220534
2013-02-28 23:57:00 -1.624220
2013-02-28 23:58:00 0.093915
2013-02-28 23:59:00 -1.087454
[84960 rows x 1 columns]
這指定了確切的停止時間(並且與上面的不同):
In [85]: dft['2013-1':'2013-2-28 00:00:00']
Out[85]:
A
2013-01-01 00:00:00 0.176444
2013-01-01 00:01:00 0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00 0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
... ...
2013-02-27 23:54:00 0.897051
2013-02-27 23:55:00 -0.309230
2013-02-27 23:56:00 1.944713
2013-02-27 23:57:00 0.369265
2013-02-27 23:58:00 0.053071
2013-02-27 23:59:00 -0.019734
2013-02-28 00:00:00 1.388189
[83521 rows x 1 columns]
我們正在停止包含的終點,因為它是索引的一部分:
In [86]: dft['2013-1-15':'2013-1-15 12:30:00']
Out[86]:
A
2013-01-15 00:00:00 0.501288
2013-01-15 00:01:00 -0.605198
2013-01-15 00:02:00 0.215146
2013-01-15 00:03:00 0.924732
2013-01-15 00:04:00 -2.228519
2013-01-15 00:05:00 1.517331
2013-01-15 00:06:00 -1.188774
... ...
2013-01-15 12:24:00 1.358314
2013-01-15 12:25:00 -0.737727
2013-01-15 12:26:00 1.838323
2013-01-15 12:27:00 -0.774090
2013-01-15 12:28:00 0.622261
2013-01-15 12:29:00 -0.631649
2013-01-15 12:30:00 0.193284
[751 rows x 1 columns]
版本0.18.0中的新功能。
DatetimeIndex
部分字串索引也適用於DataFrame
a MultiIndex
:
In [87]: dft2 = pd.DataFrame(np.random.randn(20, 1),
....: columns=['A'],
....: index=pd.MultiIndex.from_product([pd.date_range('20130101',
....: periods=10,
....: freq='12H'),
....: ['a', 'b']]))
....:
In [88]: dft2
Out[88]:
A
2013-01-01 00:00:00 a -0.659574
b 1.494522
2013-01-01 12:00:00 a -0.778425
b -0.253355
2013-01-02 00:00:00 a -2.816159
b -1.210929
2013-01-02 12:00:00 a 0.144669
... ...
2013-01-04 00:00:00 b -1.624463
2013-01-04 12:00:00 a 0.056912
b 0.149867
2013-01-05 00:00:00 a -1.256173
b 2.324544
2013-01-05 12:00:00 a -1.067396
b -0.660996
[20 rows x 1 columns]
In [89]: dft2.loc['2013-01-05']
Out[89]:
A
2013-01-05 00:00:00 a -1.256173
b 2.324544
2013-01-05 12:00:00 a -1.067396
b -0.660996
In [90]: idx = pd.IndexSlice
In [91]: dft2 = dft2.swaplevel(0, 1).sort_index()
In [92]: dft2.loc[idx[:, '2013-01-05'], :]
Out[92]:
A
a 2013-01-05 00:00:00 -1.256173
2013-01-05 12:00:00 -1.067396
b 2013-01-05 00:00:00 2.324544
2013-01-05 12:00:00 -0.660996
切片與精確匹配
版本0.20.0已更改。
用作索引引數的相同字串可以被視為切片或完全匹配,具體取決於索引的解析度。如果字串不如索引準確,則將其視為切片,否則視為完全匹配。
考慮Series
具有分鐘解析度索引的物件:
In [93]: series_minute = pd.Series([1, 2, 3],
....: pd.DatetimeIndex(['2011-12-31 23:59:00',
....: '2012-01-01 00:00:00',
....: '2012-01-01 00:02:00']))
....:
In [94]: series_minute.index.resolution
Out[94]: 'minute'
時間戳字串不如一分鐘準確給出一個Series
物件。
In [95]: series_minute['2011-12-31 23']
Out[95]:
2011-12-31 23:59:00 1
dtype: int64
具有分鐘解析度(或更準確)的時間戳字串,而是給出標量,即它不會轉換為切片。
In [96]: series_minute['2011-12-31 23:59']
Out[96]: 1
In [97]: series_minute['2011-12-31 23:59:00']
Out[97]: 1
如果索引解析度是秒,那麼分鐘準確的時間戳給出了 Series
。
In [98]: series_second = pd.Series([1, 2, 3],
....: pd.DatetimeIndex(['2011-12-31 23:59:59',
....: '2012-01-01 00:00:00',
....: '2012-01-01 00:00:01']))
....:
In [99]: series_second.index.resolution
Out[99]: 'second'
In [100]: series_second['2011-12-31 23:59']
Out[100]:
2011-12-31 23:59:59 1
dtype: int64
如果時間戳字串作為一個切片進行處理,它可被用於索引DataFrame
與[]
為好。
In [101]: dft_minute = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]},
.....: index=series_minute.index)
.....:
In [102]: dft_minute['2011-12-31 23']
Out[102]:
a b
2011-12-31 23:59:00 1 4
警告:但是,如果將字串視為完全匹配,則
DataFrame
s中的選擇[]
將按列而不是按行進行,請參閱索引基礎知識。例如將提高為具有相同的解析度指標,有這樣的名字沒有列:dft_minute['2011-12-31 23:59']
KeyError
'2012-12-31 23:59'
要始終具有明確的選擇,無論該行是被視為切片還是單個選擇,請使用
.loc
。In [103]: dft_minute.loc['2011-12-31 23:59'] Out[103]: a 1 b 4 Name: 2011-12-31 23:59:00, dtype: int64
還要注意,DatetimeIndex
解析度不能比白天精確。
In [104]: series_monthly = pd.Series([1, 2, 3],
.....: pd.DatetimeIndex(['2011-12',
.....: '2012-01',
.....: '2012-02']))
.....:
In [105]: series_monthly.index.resolution
Out[105]: 'day'
In [106]: series_monthly['2011-12'] # returns Series
Out[106]:
2011-12-01 1
dtype: int64
精確索引
如前一節所述DatetimeIndex
,使用部分字串索引a 取決於句點的“準確性”,換句話說,間隔與索引的解析度有何關聯。相比之下,使用Timestamp
或datetime
物件進行索引是準確的,因為物件具有確切的含義。這些也遵循包含兩個端點的語義。
這些Timestamp
和datetime
物件有確切的和,即使他們沒有明確規定(他們是)。hours, minutes,
seconds
0
In [107]: dft[datetime(2013, 1, 1):datetime(2013,2,28)]
Out[107]:
A
2013-01-01 00:00:00 0.176444
2013-01-01 00:01:00 0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00 0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
... ...
2013-02-27 23:54:00 0.897051
2013-02-27 23:55:00 -0.309230
2013-02-27 23:56:00 1.944713
2013-02-27 23:57:00 0.369265
2013-02-27 23:58:00 0.053071
2013-02-27 23:59:00 -0.019734
2013-02-28 00:00:00 1.388189
[83521 rows x 1 columns]
沒有預設值。
In [108]: dft[datetime(2013, 1, 1, 10, 12, 0):datetime(2013, 2, 28, 10, 12, 0)]
Out[108]:
A
2013-01-01 10:12:00 -0.246733
2013-01-01 10:13:00 -1.429225
2013-01-01 10:14:00 -1.265339
2013-01-01 10:15:00 0.710986
2013-01-01 10:16:00 -0.818200
2013-01-01 10:17:00 0.543542
2013-01-01 10:18:00 1.577713
... ...
2013-02-28 10:06:00 0.311249
2013-02-28 10:07:00 2.366080
2013-02-28 10:08:00 -0.490372
2013-02-28 10:09:00 0.373340
2013-02-28 10:10:00 0.638442
2013-02-28 10:11:00 1.330135
2013-02-28 10:12:00 -0.945450
[83521 rows x 1 columns]
截斷和花式索引
甲truncate()
提供方便的功能類似於切片。請注意,truncate
對於任何未指定的日期元件,假設為0 DatetimeIndex
,與切片相反,返回任何部分匹配的日期:
In [109]: rng2 = pd.date_range('2011-01-01', '2012-01-01', freq='W')
In [110]: ts2 = pd.Series(np.random.randn(len(rng2)), index=rng2)
In [111]: ts2.truncate(before='2011-11', after='2011-12')
Out[111]:
2011-11-06 -0.773743
2011-11-13 0.247216
2011-11-20 0.591308
2011-11-27 2.228500
Freq: W-SUN, dtype: float64
In [112]: ts2['2011-11':'2011-12']
Out[112]:
2011-11-06 -0.773743
2011-11-13 0.247216
2011-11-20 0.591308
2011-11-27 2.228500
2011-12-04 0.838769
2011-12-11 0.658538
2011-12-18 0.567353
2011-12-25 -1.076735
Freq: W-SUN, dtype: float64
即使複雜的花式索引打破了DatetimeIndex
頻率規律也會導致a DatetimeIndex
,雖然頻率會丟失:
In [113]: ts2[[0, 2, 6]].index
Out[113]: DatetimeIndex(['2011-01-02', '2011-01-16', '2011-02-13'], dtype='datetime64[ns]', freq=None)
時間/日期元件
有一些時間/日期屬性可供人們訪問,Timestamp
或者有一組時間戳,如a DatetimeIndex
。
屬性 | 描述 |
---|---|
year | 日期時間 |
month | 日期時間的月份 |
day | 日期時間的日子 |
hour | 日期時間的小時 |
minute | 日期時間的分鐘 |
second | 日期時間的秒數 |
ms | 日期時間的微秒 |
ns | 日期時間的納秒 |
date | 返回datetime.date(不包含時區資訊) |
time | 返回datetime.time(不包含時區資訊) |
DAYOFYEAR | 一年中的序數日 |
WEEKOFYEAR | 一年中的一週序數 |
week | 一年中的一週序數 |
dayofweek | 星期一= 0,星期日= 6的星期幾 |
weekday | 星期一= 0,星期日= 6的星期幾 |
weekday_name | 一週中的一天的名字(例如:星期五) |
quarter | 日期的四分之一:Jan-Mar = 1,Apr-Jun = 2等 |
days_in_month | 日期時間的月份天數 |
is_month_start | 邏輯指示是否每月的第一天(由頻率定義) |
is_month_end | 邏輯指示是否每月的最後一天(由頻率定義) |
is_quarter_start | 邏輯指示季度的第一天(由頻率定義) |
is_quarter_end | 邏輯指示是否是季度的最後一天(由頻率定義) |
is_year_start | 邏輯指示年份的第一天(由頻率定義) |
is_year_end | 邏輯指示年份的最後一天(由頻率定義) |
is_leap_year | 邏輯指示日期是否屬於閏年 |
此外,如果您具有Series
datetimelike值,則可以通過訪問器訪問這些屬性.dt
,詳見.dt訪問器一節。
DateOffset物件(時間量偏移方法)*
在前面的例子中,我們DatetimeIndex
通過將 諸如“M”,“W”和“BM”的頻率字串傳遞給freq
關鍵字來建立各種頻率的物件。在引擎蓋下,這些頻率字串被轉換為例項DateOffset
,其表示常規頻率增量。“月”,“營業日”或“一小時”等特定偏移邏輯在其各個子類中表示。
類別名稱 | 描述 |
---|---|
DateOffset | 通用偏移類,預設為1個日曆日 |
BDAY | 營業日(工作日) |
CDay | 自定義工作日 |
Week | 一週,任選地固定在一週的一天 |
WeekOfMonth | 每個月的第y周的第x天 |
LastWeekOfMonth | 每個月最後一週的第x天 |
MonthEnd | 日曆月結束 |
MonthBegin | 日曆月開始 |
BMonthEnd | 營業月末 |
BMonthBegin | 營業月開始 |
CBMonthEnd | 定製業務月末 |
CBMonthBegin | 自定義營業月開始 |
SemiMonthEnd | 15日(或其他日__月)和日曆月結束 |
SemiMonthBegin | 15日(或其他日__月)和日曆月開始 |
QuarterEnd | 日曆季結束 |
QuarterBegin | 日曆季開始 |
BQuarterEnd | 業務季結束 |
BQuarterBegin | 營業季開始 |
FY5253Quarter | 零售(又名52-53周)季度 |
YearEnd | 日曆年結束 |
YearBegin | 日曆年開始 |
BYearEnd | 業務年度結束 |
BYearBegin | 營業年開始 |
FY5253 | 零售(又名52-53周)年 |
BusinessHour | 營業時間 |
CustomBusinessHour | 定製營業時間 |
Hour | 一小時 |
Minute | 一分鐘 |
Second | 一秒 |
Milli | 一毫秒 |
Micro | 一微秒 |
Nano | 一納秒 |
基本DateOffset
採用相同的引數 dateutil.relativedelta
,其工作方式如下:
In [114]: d = datetime(2008, 8, 18, 9, 0)
In [115]: d + relativedelta(months=4, days=5)
Out[115]: datetime.datetime(2008, 12, 23, 9, 0)
我們可以做同樣的事情DateOffset
:
In [116]: from pandas.tseries.offsets import *
In [117]: d + DateOffset(months=4, days=5)
Out[117]: Timestamp('2008-12-23 09:00:00')
DateOffset
物件的主要特徵是:
- 可以向/從日期時間物件新增/減去它以獲得移位日期。
- 它可以乘以整數(正數或負數),以便多次應用增量。
- 它具有
rollforward()
和rollback()
用於向前或向後移動日期下一首或上“抵消日期”的方法。
DateOffset
定義指定apply
自定義日期增量邏輯的函式的子類,例如新增工作日:
class BDay(DateOffset):
"""工作日之間的DateOffset遞增"""
def apply(self, other):
...
In [118]: d - 5 * BDay()
Out[118]: Timestamp('2008-08-11 09:00:00')
In [119]: d + BMonthEn