Python 的日期時間處理模組繁多,從內建的 datetime、第三方函式庫 dateutil、時區處理的 pytz,到 NumPy 的 datetime64 與 Pandas 的時間序列工具,各有其適用場景。datetime 和 dateutil 提供基礎功能,但處理大量資料時效率不足。pytz 則專注於時區問題,解決跨區域時間轉換的痛點。針對大量日期時間資料,NumPy 的 datetime64 以 64 位元整數編碼日期,提供高效的儲存和運算能力。Pandas 建立在 NumPy 基礎上,提供更進階的時間序列工具,例如 Timestamp 和 DatetimeIndex,方便建立和操作時間索引,簡化時間序列資料的處理流程,更適合處理實際應用中的時間序列資料。
日期和時間在Python中的處理
Python提供了多種日期和時間的表示形式,包括datetime和dateutil模組。瞭解這些工具對於使用玄貓提供的時間序列工具非常重要。
原生Python日期和時間:datetime和dateutil
Python的內建datetime模組提供了基本的日期和時間物件。配合第三方的dateutil模組,可以快速執行許多有用的功能。例如,使用datetime類別可以手動建立日期:
from datetime import datetime
datetime(year=2021, month=7, day=4)
或者,使用dateutil模組,可以從各種字串格式中解析日期:
from dateutil import parser
date = parser.parse("2021年7月4日")
一旦你有了datetime物件,就可以執行各種操作,例如印出星期幾:
date.strftime('%A')
這裡使用了標準的字串格式程式碼'%A'來印出星期幾。你可以在Python的datetime檔案中找到更多關於strftime的資訊。dateutil的線上檔案中也有更多有用的日期工具的介紹。
時區問題和pytz
另一個需要注意的套件是pytz,它包含了處理時間序列資料中最令人頭痛的元素:時區。
datetime和dateutil的強大之處
datetime和dateutil的強大之處在於其靈活性和易用性。你可以使用這些物件和其內建方法輕鬆地執行大多數操作。但是,當你想要處理大量日期和時間陣列時,它們就不夠用了。就像Python數值變數的列表不如NumPy風格的打字陣列一樣,Python datetime物件的列表也不如打字日期陣列。
打字時間陣列:NumPy的datetime64
NumPy的datetime64資料型別將日期編碼為64位整數,因此可以緊湊地表示日期陣列,並以高效的方式運算。datetime64需要特定的輸入格式:
import numpy as np
date = np.array('2021-07-04', dtype=np.datetime64)
內容解密:
上述程式碼示範瞭如何使用NumPy的datetime64型別建立一個日期陣列。這種資料型別允許高效地儲存和運算大量日期資料。
圖表翻譯:
圖表翻譯:
上述流程圖示範瞭如何使用Python的datetime和dateutil模組建立和操作日期,然後使用NumPy的datetime64型別高效地儲存和運算日期資料。
日期和時間運算
在進行日期和時間運算時,NumPy 提供了一種高效的方式來處理這些資料。透過使用 datetime64 型別的陣列,我們可以快速地進行向量化運算。
例如,假設我們有一個日期陣列 date,其值為 ‘2021-07-04’。我們可以使用 np.arange(12) 來生成一個從 0 到 11 的整數陣列,然後將其與 date 相加,以生成一個新的日期陣列,每個日期都比前一個日期晚一天。
import numpy as np
date = np.array('2021-07-04', dtype='datetime64[D]')
new_dates = date + np.arange(12)
print(new_dates)
輸出結果將是一個包含 12 個日期的陣列,每個日期都比前一個日期晚一天。
['2021-07-04' '2021-07-05' '2021-07-06' '2021-07-07' '2021-07-08'
'2021-07-09' '2021-07-10' '2021-07-11' '2021-07-12' '2021-07-13'
'2021-07-14' '2021-07-15']
這種運算方式比直接使用 Python 的 datetime 物件要快得多,尤其是在處理大型陣列時。
時間單位和範圍
datetime64 和相關的 timedelta64 物件都是根據一個基本時間單位的。由於 datetime64 物件的精確度有限為 64 位元,因此可編碼的時間範圍是 2^64 倍於這個基本時間單位。這意味著 datetime64 物件在時間解析度和最大時間跨度之間存在一個權衡。
例如,如果您想要以 1 納秒為時間解析度,您只能編碼 2^64 納秒的範圍,即約 600 年。NumPy 會根據輸入內容推斷所需的時間單位。例如,以下是一個以天為基礎的日期:
date = np.datetime64('2021-07-04')
print(date)
輸出結果為:
numpy.datetime64('2021-07-04')
以下是一個以分鐘為基礎的日期:
date = np.datetime64('2021-07-04 12:00')
print(date)
輸出結果為:
numpy.datetime64('2021-07-04T12:00')
內容解密:
在上述程式碼中,我們使用 np.datetime64 來建立一個 datetime64 物件。這個物件可以用來表示日期和時間,並且可以進行向量化運算。透過使用 np.arange(12) 來生成一個整數陣列,我們可以將其與 date 相加,以生成一個新的日期陣列。
圖表翻譯:
以下是使用 Plantuml 圖表來展示日期和時間運算的流程: 在這個圖表中,我們首先建立一個日期陣列,然後生成一個整數陣列。接下來,我們進行向量化運算,以生成一個新的日期陣列。最後,我們輸出結果。
日期和時間的處理:NumPy和Pandas的最佳實踐
在處理日期和時間的資料時,選擇合適的資料型別和工具是非常重要的。NumPy的datetime64資料型別提供了一種高效且靈活的方式來處理日期和時間的資料。下面,我們將探討如何使用datetime64來處理日期和時間的資料,並介紹Pandas中日期和時間的處理方法。
使用datetime64處理日期和時間
datetime64是一種高精確度的日期和時間資料型別,可以用來表示從年到秒的時間間隔。您可以使用不同的格式程式碼來指定時間單位,例如:
Y: 年M: 月W: 周D: 日h: 小時m: 分鐘s: 秒ms: 毫秒us: 微秒ns: 納秒ps: 皮秒fs: 飛秒as: 亞秒
以下是使用datetime64來表示日期和時間的範例:
import numpy as np
# 建立一個datetime64物件
dt = np.datetime64('2021-07-04 12:59:59.50', 'ns')
print(dt) # 輸出:2021-07-04T12:59:59.500000000
日期和時間的格式程式碼
下表列出了可用的日期和時間格式程式碼,以及相對和絕對時間範圍:
| 格式程式碼 | 意義 | 相對時間範圍 | 絕對時間範圍 |
|---|---|---|---|
| Y | 年 | ±9.2e18年 | [9.2e18 BC, 9.2e18 AD] |
| M | 月 | ±7.6e17年 | [7.6e17 BC, 7.6e17 AD] |
| W | 周 | ±1.7e17年 | [1.7e17 BC, 1.7e17 AD] |
| D | 日 | ±2.5e16年 | [2.5e16 BC, 2.5e16 AD] |
| h | 小時 | ±1.0e15年 | [1.0e15 BC, 1.0e15 AD] |
| m | 分鐘 | ±1.7e13年 | [1.7e13 BC, 1.7e13 AD] |
| s | 秒 | ±2.9e12年 | [2.9e9 BC, 2.9e9 AD] |
| ms | 毫秒 | ±2.9e9年 | [2.9e6 BC, 2.9e6 AD] |
| us | 微秒 | ±2.9e6年 | [290301 BC, 294241 AD] |
| ns | 納秒 | ±292年 | [1678 AD, 2262 AD] |
| ps | 皮秒 | ±106天 | [1969 AD, 1970 AD] |
| fs | 飛秒 | ±2.6小時 | [1969 AD, 1970 AD] |
| as | 亞秒 | ±9.2秒 | [1969 AD, 1970 AD] |
Pandas中的日期和時間處理
Pandas提供了一種方便的方式來處理日期和時間的資料。您可以使用pd.to_datetime()函式來將字串轉換為日期和時間物件。
import pandas as pd
# 建立一個DataFrame
df = pd.DataFrame({'date': ['2021-07-04 12:59:59.50']})
# 將date欄位轉換為日期和時間物件
df['date'] = pd.to_datetime(df['date'])
print(df)
內容解密:
在上面的範例中,我們使用了np.datetime64()函式來建立一個日期和時間物件。這個函式可以用來表示從年到秒的時間間隔。您可以使用不同的格式程式碼來指定時間單位,例如Y、M、W、D、h、m、s、ms、us、ns、ps、fs和as。
圖表翻譯:
此圖示了建立日期和時間物件的流程。首先,建立一個日期和時間物件,然後指定時間單位,最後使用np.datetime64()函式輸出日期和時間物件。
此圖示了使用Pandas將字串轉換為日期和時間物件的流程。首先,輸入一個字串,然後使用pd.to_datetime()函式,最後輸出日期和時間物件。
時間序列資料處理:Pandas 的強大工具
Pandas 是一個強大的 Python 函式庫,提供了高效的時間序列資料處理工具。它結合了 datetime 和 dateutil 的易用性,與 numpy.datetime64 的高效儲存和向量化介面。透過 Pandas,我們可以輕鬆地建立時間戳記物件(Timestamp),並將其用於構建時間索引(DatetimeIndex),以便索引 Series 或 DataFrame 中的資料。
時間戳記物件(Timestamp)
Pandas 的 Timestamp 物件是時間序列資料處理的基礎。它提供了一個方便的方式來表示和操作時間日期。例如,我們可以使用 Pandas 的工具來解析一個格式靈活的字串日期,並使用格式程式碼來輸出星期幾:
import pandas as pd
date = pd.to_datetime("4th of July, 2021")
print(date) # 輸出:Timestamp('2021-07-04 00:00:00')
day_of_week = date.strftime('%A')
print(day_of_week) # 輸出:'Sunday'
此外,我們可以直接在 Timestamp 物件上進行 NumPy 樣式的向量化操作:
import numpy as np
date = pd.to_datetime("4th of July, 2021")
dates = date + pd.to_timedelta(np.arange(12), 'D')
print(dates)
# 輸出:DatetimeIndex(['2021-07-04', '2021-07-05', '2021-07-06',...])
時間索引(DatetimeIndex)
Pandas 的 DatetimeIndex 是一個特殊的索引,用於時間序列資料。它提供了一個方便的方式來索引和操作時間序列資料。例如,我們可以建立一個 Series 物件,其索引是時間索引:
index = pd.DatetimeIndex(['2020-07-04', '2020-08-04', '2021-07-04', '2021-08-04'])
data = pd.Series([0, 1, 2, 3], index=index)
print(data)
# 輸出:
# 2020-07-04 0
# 2020-08-04 1
# 2021-07-04 2
# 2021-08-04 3
在下一節中,我們將更深入地探討使用 Pandas 工具來操作時間序列資料。
時間序列資料結構
時間序列資料結構是用於儲存和操作時間序列資料的基本單位。Pandas 提供了多種時間序列資料結構,包括 Timestamp、Period、Timedelta 等。
Timestamp
Timestamp 是 Pandas 中用於表示時間戳的型別。它是根據 numpy.datetime64 的,相比 Python 的 native datetime 型別更為高效。Timestamp 的索引結構是 DatetimeIndex。
Period
Period 是 Pandas 中用於表示時間週期的型別。它編碼了一個固定頻率的間隔,根據 numpy.datetime64。Period 的索引結構是 PeriodIndex。
Timedelta
Timedelta 是 Pandas 中用於表示時間差或持續時間的型別。它是根據 numpy.timedelta64 的,相比 Python 的 native datetime.timedelta 型別更為高效。Timedelta 的索引結構是 TimedeltaIndex。
基本使用
可以使用 pd.to_datetime 函式來解析多種格式的日期和時間。傳遞單個日期給 pd.to_datetime 會傳回一個 Timestamp 物件;傳遞多個日期會傳回一個 DatetimeIndex 物件。
import pandas as pd
from datetime import datetime
# 定義日期列表
dates = [datetime(2021, 7, 3), '4th of July, 2021', '2021-Jul-6', '07-07-2021', '20210708']
# 使用 pd.to_datetime 解析日期
parsed_dates = pd.to_datetime(dates)
print(parsed_dates)
內容解密:
在上述程式碼中,我們首先匯入必要的函式庫,包括 pandas 和 datetime。然後,我們定義了一個日期列表,其中包含不同格式的日期。接著,我們使用 pd.to_datetime 函式來解析這些日期。最後,我們印出解析後的日期列表。
時間序列索引
時間序列索引是用於索引時間序列資料的基本單位。Pandas 提供了多種時間序列索引,包括 DatetimeIndex、PeriodIndex 和 TimedeltaIndex。
DatetimeIndex
DatetimeIndex 是 Pandas 中用於表示日期和時間的索引型別。它是根據 numpy.datetime64 的,相比 Python 的 native datetime 型別更為高效。
import pandas as pd
# 定義日期列表
dates = ['2021-07-03', '2021-07-04', '2021-07-05']
# 使用 pd.to_datetime 解析日期
datetime_index = pd.to_datetime(dates)
print(datetime_index)
PeriodIndex
PeriodIndex 是 Pandas 中用於表示時間週期的索引型別。它編碼了一個固定頻率的間隔,根據 numpy.datetime64。
import pandas as pd
# 定義時間週期列表
periods = ['2021-07', '2021-08', '2021-09']
# 使用 pd.PeriodIndex 建立 PeriodIndex
period_index = pd.PeriodIndex(periods, freq='M')
print(period_index)
TimedeltaIndex
TimedeltaIndex 是 Pandas 中用於表示時間差或持續時間的索引型別。它是根據 numpy.timedelta64 的,相比 Python 的 native datetime.timedelta 型別更為高效。
import pandas as pd
# 定義時間差列表
timedeltas = ['1 day', '2 days', '3 days']
# 使用 pd.to_timedelta 解析時間差
timedelta_index = pd.to_timedelta(timedeltas)
print(timedelta_index)
圖表翻譯:
此圖示展示了 Pandas 中的時間序列資料結構和索引型別,包括 Timestamp、Period、Timedelta、DatetimeIndex、PeriodIndex 和 TimedeltaIndex。每個型別都有其特定的用途和優點,根據具體需求選擇合適的型別以進行時間序列資料的儲存和操作。
日期和時間序列的處理
在時間序列分析中,日期和時間的處理是非常重要的。Pandas提供了多種工具來處理日期和時間,包括DatetimeIndex、PeriodIndex和TimedeltaIndex。
DatetimeIndex
DatetimeIndex是一種用於表示日期和時間的索引。它可以透過pd.to_datetime()函式建立,也可以透過從字串或其他日期格式中解析日期來建立。
import pandas as pd
dates = pd.to_datetime(['2021-07-03', '2021-07-04', '2021-07-06', '2021-07-07', '2021-07-08'])
print(dates)
PeriodIndex
PeriodIndex是一種用於表示日期和時間的索引,與DatetimeIndex相比,它更適合用於表示日期範圍。可以透過to_period()函式將DatetimeIndex轉換為PeriodIndex。
periods = dates.to_period('D')
print(periods)
TimedeltaIndex
TimedeltaIndex是一種用於表示時間間隔的索引。它可以透過從日期中減去另一個日期來建立。
timedeltas = dates - dates[0]
print(timedeltas)
日期範圍
Pandas提供了多種函式來建立日期範圍,包括pd.date_range()、pd.period_range()和pd.timedelta_range()。
date_range = pd.date_range('2015-07-03', '2015-07-10')
print(date_range)
或者,可以指定開始日期和期數來建立日期範圍。
date_range = pd.date_range('2015-07-03', periods=8)
print(date_range)
時間序列生成
時間序列是許多實際應用中非常重要的資料結構,尤其是在金融、氣象、交通等領域。Pandas 提供了強大的工具來生成和操作時間序列。
日期範圍生成
pd.date_range 函式可以用來生成一個指定範圍的日期序列。例如,下面的程式碼生成了一個從 2015-07-03 到 2015-07-10 的日期序列,每天一個日期:
import pandas as pd
date_range = pd.date_range('2015-07-03', periods=8)
print(date_range)
輸出結果:
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 引數來修改。例如,下面的程式碼生成了一個從 2015-07-03 00:00:00 到 2015-07-03 07:00:00 的時間序列,每小時一個時間點:
hourly_range = pd.date_range('2015-07-03', periods=8, freq='H')
print(hourly_range)
輸出結果:
DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 01:00:00',
'2015-07-03 02:00:00', '2015-07-03 03:00:00',
'2015-07-03 04:00:00', '2015-07-03 05:00:00',
'2015-07-03 06:00:00', '2015-07-03 07:00:00'],
dtype='datetime64[ns]', freq='H')
期別範圍生成
pd.period_range 函式可以用來生成一個指定範圍的期別序列。例如,下面的程式碼生成了一個從 2015-07 到 2016-02 的月份序列,每月一個期別:
period_range = pd.period_range('2015-07', periods=8, freq='M')
print(period_range)
輸出結果:
PeriodIndex(['2015-07', '2015-08', '2015-09', '2015-10', '2015-11',
'2015-12', '2016-01', '2016-02'],
dtype='period[M]')
時間間隔範圍生成
pd.timedelta_range 函式可以用來生成一個指定範圍的時間間隔序列。例如,下面的程式碼生成了一個從 0 小時到 5 小時的時間間隔序列,每小時一個時間間隔:
timedelta_range = pd.timedelta_range(0, periods=6, freq='H')
print(timedelta_range)
輸出結果:
TimedeltaIndex(['0 days 00:00:00', '0 days 01:00:00', '0 days 02:00:00',
'0 days 03:00:00', '0 days 04:00:00', '0 days 05:00:00'],
dtype='timedelta64[ns]', freq='H')
圖表翻譯:
圖表解釋:本圖表描述了 Pandas 中的時間序列生成過程,從日期範圍開始,到時間間隔修改,然後到期別範圍,最後到時間間隔範圍,最終輸出結果。
時間序列工具中的頻率和偏移
在Pandas的時間序列工具中,頻率或日期偏移的概念至關重要。以下表格總結了主要的程式碼;如前幾節所示的D(天)和H(小時)程式碼,我們可以使用這些程式碼來指定任何所需的頻率間隔。
頻率程式碼列表
| 程式碼 | 描述 | 程式碼 | 描述 |
|---|---|---|---|
| D | 曆日 | B | 商業日 |
| W | 週期 | M | 月末 |
| BM | 商業月末 | Q | 季末 |
| BQ | 商業季末 | A | 年末 |
| BA | 商業年末 | H | 小時 |
這些頻率程式碼可以用來指定時間序列的間隔,例如每日、每週、每月等。透過使用這些程式碼,我們可以輕鬆地進行時間序列分析和操作。
內容解密:
在上面的表格中,我們可以看到不同的頻率程式碼及其對應的描述。例如,D程式碼代表曆日,B程式碼代表商業日。這些程式碼可以用來指定時間序列的間隔,例如每日、每週、每月等。
import pandas as pd
# 建立一個時間序列
date_range = pd.date_range(start='2022-01-01', end='2022-01-31', freq='D')
# 列印時間序列
print(date_range)
在上面的程式碼中,我們使用pd.date_range函式建立了一個時間序列,從2022-01-01到2022-01-31,每天一個間隔。這裡我們使用了D程式碼來指定頻率間隔。
圖表翻譯:
此圖示為Pandas時間序列工具中的頻率程式碼列表。 在上面的Plantuml圖表中,我們可以看到Pandas時間序列工具中的頻率程式碼列表。每個程式碼都對應著一個特定的頻率間隔,例如曆日、商業日、週期等。這些程式碼可以用來指定時間序列的間隔,從而進行時間序列分析和操作。
時間單位與頻率設定
在設定時間單位和頻率時,瞭解不同時間單位的縮寫和含義是非常重要的。以下是常見的時間單位縮寫:
- H: 小時(Hours)
- T: 分鐘(Minutes)
- S: 秒(Seconds)
- L: 毫秒(Milliseconds)
- U: 微秒(Microseconds)
- N: 納秒(Nanoseconds)
除了基本的時間單位,還有與週期相關的設定,例如月度、季度和年度頻率。這些頻率通常在指定期結束時被標記,但透過在頻率程式碼後新增「S」字尾,可以改為在期初被標記。
頻率程式碼列表
下表列出了與週期相關的頻率程式碼,包括月度、季度和年度的開始和結束標記。
| 程式碼 | 描述 | 程式碼 | 描述 |
|---|---|---|---|
| MS | 月初 | BMS | 商業月初 |
| QS | 季度初 | … | … |
這些頻率程式碼對於設定和管理定期任務、報告和其他需要按特定時間間隔執行的任務非常重要。透過使用正確的頻率程式碼,可以確保任務按預期執行,同時也能夠根據需要進行調整。
範例應用
在實際應用中,這些時間單位和頻率程式碼可以用於各種場景。例如,設定一個每月初執行的任務,可以使用「MS」程式碼來標記任務的執行時間。同樣,季度初的任務可以使用「QS」程式碼。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Python日期時間處理NumPyPandas最佳實踐
package "Pandas 資料處理" {
package "資料結構" {
component [Series
一維陣列] as series
component [DataFrame
二維表格] as df
component [Index
索引] as index
}
package "資料操作" {
component [選取 Selection] as select
component [篩選 Filtering] as filter
component [分組 GroupBy] as group
component [合併 Merge/Join] as merge
}
package "資料轉換" {
component [重塑 Reshape] as reshape
component [透視表 Pivot] as pivot
component [聚合 Aggregation] as agg
}
}
series --> df : 組成
index --> df : 索引
df --> select : loc/iloc
df --> filter : 布林索引
df --> group : 分組運算
group --> agg : 聚合函數
df --> merge : 合併資料
df --> reshape : melt/stack
reshape --> pivot : 重新組織
note right of df
核心資料結構
類似 Excel 表格
end note
@enduml圖表翻譯:
此圖示為設定時間單位和執行任務的流程圖。首先,需要設定時間單位,然後選擇合適的頻率程式碼。接著,根據選定的頻率程式碼執行任務,最後確認任務的結果。
從技術架構視角來看,Python處理日期和時間的核心機制,涵蓋了原生datetime模組、功能強大的dateutil套件以及針對時區問題的pytz套件。文章深入剖析了datetime和dateutil的靈活性和易用性,尤其是在處理少量日期和時間資料的優勢。然而,對於大量資料處理,NumPy的datetime64資料型別則展現出更高的效率,它以64位整數編碼日期,實作了緊湊的陣列表示和高效的向量化運算。同時,文章也明確指出了datetime64在時間精確度和最大時間跨度之間的權衡,以及不同時間單位下NumPy的型別推斷機制。更進一步,文章探討了Pandas如何結合datetime、dateutil和numpy.datetime64的優點,提供Timestamp和DatetimeIndex等更強大的時間序列處理工具,以及如何利用這些工具進行時間序列的生成、索引和操作。玄貓認為,對於需要高效處理時間序列資料的開發者,深入理解NumPy和Pandas提供的工具至關重要,同時也需根據實際需求選擇合適的工具和策略,才能最大程度地提升效率並避免潛在的效能瓶頸。對於初學者,建議從datetime和dateutil入手,逐步掌握Pandas的進階用法。未來,隨著資料規模的持續增長,預計會有更多針對時間序列資料處理的最佳化工具和技術出現,值得持續關注。