Educoder python Pandas高效化運算與時間序列處理 第2關:Pandas的日期與時間工具


任務描述

本關任務:根據預期輸出,創建三種不同索引的數據結構。

相關知識

Pandas是爲金融模型而創建的,所以擁有一些功能非常強大的日期、時間、帶時間索引數據的處理工具。

本關卡介紹的日期與時間數據主要包含三類:

  • 時間戳:表示某個具體的時間點;(例如201574日上午 7 點)

  • 時間間隔與週期:期表示開始時間點與結束時間點之間的時間長度,例如2015年(指的是201511日至20151231日這段時間間隔)。週期通常是指一種特殊形式的時間間隔,每個間隔長度相同,彼此之間不會重疊;(例如,以24小時爲週期構成每一天)

  • 時間增量或持續時間:表示精確的時間長度。(例如,某程序運行持續時間22.56秒)

Python 的日期與時間工具

原生Python中也有處理日期與時間的工具,它與Pandas中處理時間的工具有着千絲萬縷的聯繫。

Python的日期與時間功能都在標準庫的datetime模塊和第三方庫dateutil模塊。

如果你處理的時間數據量比較大,那麼速度就會比較慢,這時就需要使用到NumPy中已經被編碼的日期類型數組了。

NumPy中的datetime64類型

Python原生日期格式的性能弱點促使NumPy團隊爲NumPy增加了自己的時間序列類型。datetime64類型將日期編碼爲64位整數,這樣可以讓日期數組非常緊湊(節省內存)。


 
  1. In[3]:import numpy as np
  2. date = np.array('2015-07-04', dtype=np.datetime64)
  3. date
  4. Out[3]:array(datetime.date(2015, 7, 4), dtype='datetime64[D]')

有了這個日期格式,即可以進行快速的向量化運算:


 
  1. In[4]:date + np.arange(12) #由於date是datetime類型,所以向量化運算也是datetime類型的運算
  2. Out[4]:
  3. array(['2015-07-04', '2015-07-05', '2015-07-06', '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10', '2015-07-11', '2015-07-12', '2015-07-13', '2015-07-14', '2015-07-15'], dtype='datetime64[D]')

由於datetime64對象是64位精度,所以可編碼的時間範圍可以是基本單元的 264倍。datetime64可以在時間精度最大時間跨度之間達成了一種平衡,也就是說,NumPy會自動判斷輸入時間所需要使用的時間單位。


 
  1. In[5]: np.datetime64('2015-07-04') # 天爲單位
  2. Out[5]: numpy.datetime64('2015-07-04')
  3. In[6]: np.datetime64('2015-07-04 12:00') # 分鐘爲單位
  4. Out[6]: numpy.datetime64('2015-07-04T12:00')
  5. In[7]: np.datetime64('2015-07-04 12:59:59.50', 'ns') # 手動設置時間單位
  6. Out[7]: numpy.datetime64('2015-07-04T12:59:59.500000000')

日期與時間單位格式代碼表如下:

代碼 含義 時間跨度(相對) 時間跨度(絕對)
Y 年(year ±9.2e18 [9.2e18 BC, 9.2e18 AD]
M 月(month ±7.6e17 [7.6e17 BC, 7.6e17 AD]
W 周(week ±1.7e17 [1.7e17 BC, 1.7e17 AD]
D 日(day ±2.5e16 [2.5e16 BC, 2.5e16 AD]
h 時(hour ±1.0e15 [1.0e15 BC, 1.0e15 AD]
m 分(minute ±1.7e13 [1.7e13 BC, 1.7e13 AD]
s 秒(second ±2.9e12 [2.9e9 BC, 2.9e9 AD]
ms 毫秒(millisecond ±2.9e9 [2.9e6 BC, 2.9e6 AD]
us 微秒(microsecond ±2.9e6 [290301 BC, 294241 AD]
ns 納秒(nanosecond ±292 [1678 AD, 2262 AD]
ps 皮秒(picosecond ±106 [1969 AD, 1970 AD]
fs 飛秒(femtosecond ±2.6小時 [1969 AD, 1970 AD]
as 原秒(attosecond ±9.2 [1969 AD, 1970 AD

Pandas的日期與時間工具

Pandas中的datetime是結合了原生PythonNumPydatetime,用來處理時間序列的基礎數據類型如下:

  • 針對時間戳數據,Pandas提供了Timestamp類型。它本質上是Python的原生datetime類型的替代品,但是在性能更好的numpy.datetime64類型的基礎上創建。對應的索引數據結構是 DatetimeIndex

  • 針對時間週期數據,Pandas提供了Period類型。這是利用numpy.datetime64類型將固定頻率的時間間隔進行編碼。對應的索引數據結構是PeriodIndex

  • 針對時間增量持續時間Pandas提供了Timedelta類型。Timedelta是一種代替Python原生datetime.timedelta類型的高性能數據結構,同樣是基於numpy.timedelta64類型。對應的索引數據結構是TimedeltaIndex

  • 最基礎的日期 / 時間對象是TimestampDatetimeIndex。這兩種對象可以直接使用,最常用的方法是pd.to_datetime()函數,。對pd.to_datetime()傳遞一個日期會返回一個Timestamp類型,傳遞一個時間序列會返回一個DatetimeIndex類型;

  • DatetimeIndex類型;

    
     
    1. In[8]:dates = pd.to_datetime([datetime(2015, 7, 3), '4th of July, 2015', '2015-Jul-6', '07-07-2015', '20150708'])
    2. dates
    3. Out[8]:DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-06', '2015-07-07', '2015-07-08'], dtype='datetime64[ns]', freq=None)
  • PeriodIndex類型,任何DatetimeIndex類型都可以通過to_period()方法和一個頻率代碼轉換成PeriodIndex類型,PeridoIndex類型可以通過to_timestamp()方法轉換爲DatetimeIndex類型。下面用D將數據轉換成單日的時間序列:

    
     
    1. In[10]: dates.to_period('D')
    2. Out[10]: PeriodIndex(['2015-07-03', '2015-07-04', '2015-07-06', '2015-07-07', '2015-07-08'], dtype='period[D]', freq='D')
  • TimedeltaIndex類型,當用一個日期減去另一個日期時,返回的結果是TimedeltaIndex類型:
    
     
    1. In[11]: dates - dates[0]
    2. Out[11]:
    3. TimedeltaIndex(['0 days', '1 days', '3 days', '4 days', '5 days'], dtype='timedelta64[ns]', freq=None)

爲了能更簡便地創建有規律的時間序列,Pandas提供了一些方法:pd.date_range()可以處理時間戳、pd.period_range()可以處理週期、pd.timedelta_range()可以處理時間間隔。

  • pd.date_range(),通過開始日期、結束日期和頻率代碼(可選的)創建一個有規律的日期序列,默認的頻率是天:

    
     
    1. In[12]:pd.date_range('2015-07-03', '2015-07-10')
    2. Out[12]:DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06', '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'], dtype='datetime64[ns]', freq='D')

    範圍不一定非是開始時間和結束時間,也可以設置週期數periods來達到改目的:

    
     
    1. In[13]:pd.date_range('2015-07-03', periods=8)
    2. Out[13]:DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06', '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'], dtype='datetime64[ns]', freq='D')

    freq表示時間間隔,默認是D,可以通過修改它來periods參數的意義:

    
     
    1. In[14]:pd.date_range('2015-07-03', periods=8, freq='H')
    2. Out[14]:
    3. DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 01:00:00',
    4. '2015-07-03 02:00:00', '2015-07-03 03:00:00',
    5. '2015-07-03 04:00:00', '2015-07-03 05:00:00',
    6. '2015-07-03 06:00:00', '2015-07-03 07:00:00'],
    7. dtype='datetime64[ns]', freq='H')
  • pd.timedelta_range(),如果要創建一個有規律的週期或時間間隔序列,pd.timedelta_range()可以實現該功能:

    
     
    1. In[15]:pd.period_range('2015-07', periods=8, freq='M')
    2. Out[15]:
    3. PeriodIndex(['2015-07', '2015-08', '2015-09', '2015-10', '2015-11', '2015-12', '2016-01', '2016-02'], dtype='int64', freq='M')

    也可以通過修改freq參數實現各種頻率的時間間隔序列。

編程要求

請先仔細閱讀右側上部代碼編輯區內給出的代碼框架,根據相關知識創建時間戳、時間週期、時間增量這三種索引的數據結構。

  • 具體要求請參見後續測試樣例。

請先仔細閱讀右側上部代碼編輯區內給出的代碼框架,再開始你的編程工作!

測試說明

平臺會對你編寫的代碼進行測試,對比你輸出的數值與實際正確的數值,只有所有數據全部計算正確才能進入下一關。

測試輸入:

2019-01-01

預期輸出:


 
  1. DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
  2. '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
  3. '2019-01-09', '2019-01-10'],
  4. dtype='datetime64[ns]', freq='D')
  5. PeriodIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
  6. '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
  7. '2019-01-09', '2019-01-10'],
  8. dtype='period[D]', freq='D')
  9. TimedeltaIndex(['01:00:00', '02:00:00', '03:00:00', '04:00:00', '05:00:00',
  10. '06:00:00', '07:00:00', '08:00:00', '09:00:00', '10:00:00'],
  11. dtype='timedelta64[ns]', freq='H')
import pandas as pd
date_number = input()
# ********** Begin ********** #
date_time = pd.date_range(date_number,periods=10,freq="D")
print(date_time)  # print(date1.to_timestamp())
date1 = pd.period_range(date_number,periods=10,freq="D")
print(date1)  # print(date_time.to_period("D"))
date_time = pd.timedelta_range("1 hours",periods=10,freq="H")
print(date_time)
# ********** End ********** #

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章