1. 程式人生 > >【Pandas】Pandas的時間與日期

【Pandas】Pandas的時間與日期

注意:重要且關鍵章節已標星

目錄

概述

無效資料

紀元時間戳

時間戳限制

索引

精確索引

引數偏移

定製營業日

營業時間

偏移別名

組合別名

錨定偏移

移位/滯後

頻率轉換

重新取樣

基礎知識

上取樣

稀疏重取樣

聚合

時區處理

事實證明,熊貓作為處理時間序列資料的工具非常成功,特別是在財務資料分析領域。使用NumPy datetime64timedelta64dtypes,我們整合了其他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_datetimedate_rangebdate_rangeDatetimeIndex
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的並不嚴格,因此如果無法在第一天解析日期,則會將其解析為dayfirstFalse。

如果傳遞單個字串to_datetime,則返回單個字串Timestamp。 Timestamp也可以接受字串輸入,但是它不接受像dayfirstformat那樣的字串解析選項,所以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整數或字串列組裝成SeriesTimestamps

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元件的標準名稱,包括:

  • 要求:yearmonthday
  • 可選:hourminutesecondmillisecondmicrosecondnanosecond

無效資料

預設行為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')

我們減去時期(UT​​C時間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_rangebdate_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可以很容易地使用的引數的各種組合等生成日期的範圍startendperiods,和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中的新功能。

指定startendperiods將生成一系列均勻間隔的日期,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”作為頻率字串傳遞時才使用weekmaskholidays引數。支援已經擴充套件,bdate_range可以使用任何自定義頻率字串。

版本0.21.0中的新功能。

bdate_range還可以使用weekmaskholidays引數生成一系列自定義頻率日期。僅在傳遞自定義頻率字串時才使用這些引數。

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物件上的shiftand tshift方法快速移動。
  • DatetimeIndex具有相同頻率的重疊物件的聯合非常快(對於快速資料對齊很重要)。
  • 通過效能,如快速訪問日期欄位yearmonth等等。
  • 正則化功能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

這種型別的切片將在一個工作DataFrameDatetimeIndex為好。由於部分字串選擇是標籤切片的一種形式,因此包括端點。這將包括在包含日期的匹配時間:

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部分字串索引也適用於DataFrameMultiIndex

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

警告:但是,如果將字串視為完全匹配,則DataFrames中的選擇[]將按列而不是按行進行,請參閱索引基礎知識。例如將提高為具有相同的解析度指標,有這樣的名字沒有列: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 取決於句點的“準確性”,換句話說,間隔與索引的解析度有何關聯。相比之下,使用Timestampdatetime物件進行索引是準確的,因為物件具有確切的含義。這些也遵循包含兩個端點的語義。

這些Timestampdatetime物件有確切的和,即使他們沒有明確規定(他們是)。hours, minutes,seconds0

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 邏輯指示日期是否屬於閏年

此外,如果您具有Seriesdatetimelike值,則可以通過訪問器訪問這些屬性.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