用pandas處理時間格式數據
- 2019 年 10 月 8 日
- 筆記
本文2023字,預計閱讀需10分鐘;
我們在處理時間相關的數據時有很多庫可以用,最常用的還是內置的datetime、time這兩個。做數據分析時基本都會導入pandas庫,而pandas提供了Timestamp和Timedelta兩個也很強大的類,並且在其官方文檔[1]上直接寫著對標datetime.datetime,所以就打算深入一下pandas內置的Timestamp的用法,在不導入datetime等庫的時候實現對時間相關數據的處理。
Timestamp基本構成
根據Timestamp的官方文檔,通過 pd.Timestamp('2019-09-26')
和 pd.Timestamp(year=2019,month=9,day=26,hour=15)
等形式可以得到一個時間戳類型的對象,Timestamp的常用輸入參數有:
- ts_input:要轉為時間戳的數據,可以是字元串,整數或小數,int/float類型要和unit搭配著用;
- unit:標識ts_input輸入int/float到底是距1970-1-1的天數還是秒數還是毫秒數等;
- year/month/day/hour/minute/second等:生成特定年月日的時間類型數據,年月日必須要有,否則會報TypeError;
- tz:timezone,時區;
整理為思維導圖如下:

Timestamp常用輸入參數
(註:可點擊查看大圖,文末附有思維導圖源文件下載方式)
Timestamp對象常用的屬性如下,根據名稱都挺容易理解是什麼數據
- .dayofyear:返回這個時間是當年的第幾天,1月1號是第1天;如
pd.Timestamp('2019-1-15').dayofyear
返回值是15;類似的屬性還有: dayofweek /weekofyear; - .day:時間戳中的天,相當於是本月第幾天;類似的屬性還有year /month /hour/ minute/ second/ nanosecond /microsecond;
- .daysinmonth:本月有多少天,如8月是31天,平年的2月是28天,也可以寫做daysinmonth;和day屬性不一樣。
- .asm8:把時間戳轉成numpy里的datetime64格式;
- .value:得到一個距離1970年1月1號的納秒數值;相當於int(pd.Timestamp('%Y-%mm-%dd').asm8);
- .isleapyear:是否是閏年,類似的屬性有is_month_end /is_quarter_end /is_quarter_start等;
整理為思維導圖如下:

Timestamp常用屬性
Timestamp對象常用的操作方法有:
- .timestamp():轉換為一個浮點數表示的POSIX時間戳;POSIX時間戳也稱Unix時間戳(Unix timestamp),是一種時間表示方式,定義為從格林威治時間1970年01月01日00時00分00秒起至現在的總秒數。和其對應的是fromtimestamp();如
pd.Timestamp.fromtimestamp(1569081600.0)=Timestamp('2019-09-22 00:00:00')
; - .strftime():轉為特定格式的字元串;如
pd.Timestamp('2019-9-22 14:12:13').strftime('%Y/%m/%d')='2019/9/22'
; - .strptime(string, format):和strftime()相反,從特定格式字元串轉時間戳,
pd.Timestamp.strptime('2019-9-22 14:12:13','%Y-%m-%d %H:%M:%S')
;關於各種字母代表哪個個時間元素(如m代表month而M程式碼minute)看datetime的文檔; - .date():把時間戳轉為一個日期類型的對象,只有年月日,
pd.Timestamp('2019-9-22 14:12:13').date()=datetime.date(2019,9,22)
; - .combine(date, time):把一個date類型和一個time類型合併為datetime類型;
- .to_datetime64():把時間戳轉為一個numpy.datetime64類型;
整理的思維導圖如下:

Timestamp常用方法
關於pd.Timedelta,時間間隔類型的知識,整理如下:

Timedelta常用屬性和方法
需求與應用
從上面的描述我們可以看到Timestamp是很強大的,和datetime相比也不遑多讓。
處理時間序列相關數據的需求主要有:生成時間類型數據、時間間隔計算、時間統計、時間索引、格式化輸出。
例如業務中的算註冊到首次付費時間、算活動開始到該用戶付費時間、算停留時長(從進入頁面到退出頁面的時間或從打開APP到退出的時間差)、獲取當前時間算年齡以進行數據驗證等。
下面主要通過一個比較綜合的示例整合以上需求:
假設有某人1年的早午晚餐消費數據(數據已脫敏),其消費時間的列是一個 '2018-12-31 17:03:26' 這樣的字元串;讀入DataFrame後需轉為Timestamp類型,並根據時間特徵標記是早餐還是午餐或晚餐,統計吃早餐天數,看早餐時間分布(箱線圖效果)等
程式碼如下:
import pandas as pd df=pd.read_excel('cost-data-2018.xls')#讀入數據 #type(df['日期'][0])=='str' df['消費時間']=pd.to_datetime(df['日期']) df=df.loc[df['子類']=='早午晚餐'] #只研究早午晚餐類型 def eatClassing(x):#早午晚餐分類 if 0<=x.hour<10: return '早餐' elif 10<=x.hour<16: return '午餐' return '晚餐' # df['ecls']=df['消費時間'].apply(eatClassing) #ecls有三種可能:早餐/午餐/晚餐 #2018吃早餐天數 df['years']=df['消費時間'].apply(lambda x:x.year) sdf=df.loc[df['years']==2018] dd=len(sdf[sdf['ecls']=='早餐']) ddr=dd/(pd.Timestamp('2018-12-31')-pd.Timestamp('2018-1-1')).days #吃早餐比率 print(dd,ddr) #繪製吃飯時間分布 df['tfs']=df['消費時間'].apply(lambda x:x.hour+x.minute/60+x.second/3600) #繪製箱線圖 import matplotlib.pyplot as plt %matplotlib inline #程式碼在jupyter notebook里跑,其他環境用plt.show() mor=df.loc[df['ecls']=='早餐',['tfs']] mor.boxplot() #同樣的方法可以畫午餐、晚餐的圖:mor1=df.loc[df['ecls']=='午餐',['tfs']] # 繪製小提琴圖(violinplot) import seaborn as sns vdf=df.sort_values(by=['消費時間']) sns.set(style="whitegrid",palette="pastel",color_codes='ture') k={'早餐':'breakfast','午餐':'lunch','晚餐':'dinner'} vdf['eclass']=vdf['ecls'].apply(lambda x:k[x]) sns.violinplot(x="eclass", y="tfs", data=vdf, split=True,inner="quart")

早餐時間箱線圖

早午晚餐的小提琴圖
[1]
Timestamp官方文檔: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Timestamp.html