用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