Pandas處理時間數據

Pandas主要涉及兩種數據結構Series和DataFrame,Series相當於數組numpy.array類似,後者相當於有表格,有行表頭index和列表頭columns

介紹一下表格數據

看下圖數據,這是一個爬蟲下來的疫情的數據,數據特點:

  1. 同一天可能有多次更新的數據
  2. 有可能會有一天沒有數據,針對美國這種,前期數據基本不公佈

需要做的處理:

  1. 希望每天僅保留最後一個時刻的數據作爲當天最終結果
  2. 對缺失的日期數據進行補充,即數據填充fill
    在這裏插入圖片描述

一、讀取表格數據read_csv

讀取表格用的是pandas的read_csv函數

# -*- encoding: utf-8 -*-
import pandas as pd
objectname = r'E:/Project/Python/DateTime/data.csv'
csv_orz = pd.read_csv(objectname, encoding='UTF-8')
print(csv_orz.head(5))
print(type(csv_orz))

csv_orz 的數據類型是DataFrame
輸出顯示:
在這裏插入圖片描述

二、pandas時間數據

1、根據時間對數據進行排序

# 根據時間進行排序
DataSort = csv_orz.sort_values(by='updateTime',ascending=False)
print(DataSort.head(5))

2、根據時間數據僅保留年月日,後面的時分秒就不用
(1)可以通過字符串slice來篩選時間數據

# 僅保留年月日
DataSort['updateTime'] = DataSort.updateTime.str.slice(0, 11)
print(DataSort.head(5))
# 日期去重
DataSortDrop = DataSort.drop_duplicates(["updateTime"],keep="first") 
print(DataSortDrop.head(5))

輸出的就是沒有時分秒,再通過drop_duplicates把重複的去掉
在這裏插入圖片描述
(2)可以通過to_datetime轉成時間格式,再用strftime來進行轉換

DataSort['updateTime'] = pd.to_datetime(DataSort['updateTime'],format='%Y-%m-%d')
DataSort['updateTime'] =  DataSort['updateTime'].apply(lambda x:x.strftime('%Y-%m-%d')) 
print(DataSort.head(5))

其實第一個format=’%Y-%m-%d’沒有什麼作用,這個就不懂原因了,但是必須先用to_datetime轉時間格式,否則是Series格式的,就沒法調用strftime。

三、DataFrame數據拼接與填充

1、取第一行的數據,保存到變量DataFinal

取數據用iloc來取

DataFinal = DataSortDrop.iloc[0,:].to_frame().T
print(DataFinal)
firstDayTime = pd.to_datetime(DataFinal['updateTime'],format='%Y-%m-%d')    
print(firstDayTime) #'2020-03-24'
# 生成一個時間格式的數據,表示一天
oneDay = pd.Timedelta(weeks=0,days=1,hours=0,minutes=0,seconds=0)
firstDayTime = firstDayTime - oneDay

上面還建立了一個變量表示oneday,一天,因爲時間數據之間的加減只能用時間格式的來處理,不能直接減數值1,所以要用Timedelta來處理

2、數據拼接

主要的思想:第二行的數據 nextDayTime 和前一行的數據 firstDayTime減oneday 進行比較,如果日期一致說明數據沒有缺失,則用concat進行拼接上去,否則就填充的空行:

for i in range(1, len(DataSortDrop)):
    nextLineData = DataSortDrop.iloc[i,:].to_frame().T
    nextDayTime = pd.to_datetime(nextLineData['updateTime'])
    if(nextDayTime.values == firstDayTime.values):
        DataFinal = pd.concat([DataFinal, nextLineData], axis=0)
        firstDayTime = firstDayTime - oneDay
    else:
        while(firstDayTime.values != nextDayTime.values):
            data = {'updateTime':str(firstDayTime.values)[2:12]}
            emptynextData = pd.DataFrame(data,index=[i])
            # print(emptynextData)
            DataFinal = pd.concat([DataFinal, emptynextData], axis=0)       
            firstDayTime = firstDayTime - oneDay
        DataFinal = pd.concat([DataFinal, nextLineData], axis=0)  
        firstDayTime = firstDayTime - oneDay
# 數據填充用後一天的數據來做
CountryFinal = DataFinal.fillna(method='ffill')  

(1)日期與日期之間的比較用value

    if(nextDayTime.values == firstDayTime.values):

(2)通過字典的方式新建一個DataFrame數據

    data = {'updateTime':str(firstDayTime.values)[2:12]}
    emptynextData = pd.DataFrame(data,index=[i])

(3)通過concat進行數據拼接,用 axis 設置行拼接或者列拼接,它可以自動對齊updateTime數據

	DataFinal = pd.concat([DataFinal, nextLineData], axis=0)
	DataFinal = pd.concat([DataFinal, emptynextData], axis=0)

(4)數據填充,直接用後項填充,就是用前一天的數據補充空缺的數據

CountryFinal = DataFinal.fillna(method='ffill')  

四、日期數據(擴)

這裏是引用:https://www.cnblogs.com/nxf-rabbit75/p/10660317.html#auto_id_0

pandas的實際類型主要分爲:

  • timestamp(時間戳)
  • period(時期)
  • timedelta(時間間隔)

常用的日期處理函數有:

  • pd.to_datetime()
  • pd.to_period()
  • pd.date_range()
  • pd.period_range
  • resample

1、pd.Timestamp()時間戳

#定義timestamp
t1=pd.Timestamp('2019-01-10')
t2=pd.Timestamp('2018-12-10')
print(f't1= {t1}')
print(f't2= {t2}')
print(f't1與t2時間間隔:{(t1-t2).days}天')
#獲取當前時間
now=pd.datetime.now()
print(now)
print(now.strftime('%Y-%m-%d'))

輸出結果:
在這裏插入圖片描述

2、pd.Timedelta()實現datetime加減

對日期和時間進行加減實際上就是把datetime往後或往前計算,得到新的datetime。加減可以直接用+和-運算符,不過需要導入timedelta這個類:

#時間間隔
timeTmp = pd.Timedelta(days=5, minutes=50, seconds=20, milliseconds=10, microseconds=10, nanoseconds=10)
print(timeTmp)
#計算當前時間往後100天的日期
dt = now + pd.Timedelta(days=100)
#只顯示年月日
print(dt.strftime('%Y-%m-%d'))
>>5 days 00:50:20.010010
>>2020-07-07

3、pd.Period()

#定義時期period,默認是A-DEC,代表年份,以12月作爲最後一個月
p1=pd.Period('2019')
p2=pd.Period('2018')
print(f'p1={p1}年')
print(f'p2={p2}年')
print(f'p1和p2間隔{p1-p2}年')
#可以直接+、-整數(代表年)
print(f'十年前是{p1-10}年')
>>p1=2019>>p2=2018>>p1和p2間隔<YearEnd: month=12>>>十年前是2009

通過asfreq轉換時期頻率

#以第一個月算,p1前面已賦值爲2019年
print(p1.asfreq('M','start'))
#以最後一個月算
print(p1.asfreq('M','end'))
>>2019-01
>>2019-12

財報季度

p = pd.Period('2019Q3',freq='Q-DEC')
#起始月日
print(p.asfreq('D','start'))
#結束月日
print(p.asfreq('D','end'))
>>2019-07-01
>>2019-09-30

4、pd.to_timestamp() 時間戳和時期相互轉換

print(p1.to_timestamp(how='end'))
print(p1.to_timestamp(how='start'))
>>2019-12-31 23:59:59.999999999
>>2019-01-01 00:00:00

5、pd.to_period() 時間戳轉爲時期

#t1前面賦值爲'2019-1-10'
#轉換爲月時期
print(t1.to_period('M'))
#轉換爲日時期
print(t1.to_period('D'))
print(t1.to_period('W'))
>>2019-01
>>2019-01-10
>>2019-01-07/2019-01-13

6、pd.to_datetime()

pandas.to_datetime(arg,errors ='raise',utc = Noneformat = None,unit = None)

在這裏插入圖片描述

(1)獲取指定的時間和日期

當數據很多,且日期格式不標準時的時候,可以使用to_datetime,將DataFrame中的時間轉換成統一標準。
例如:df[’'date]數據類型爲“object”,通過pd.to_datetime將該列數據轉換爲時間類型,即datetime。

df['date_formatted']=pd.to_datetime(df['date'],format='%Y-%m-%d')
value = '2019-04-06'
print(pd.datetime.strptime(value,'%Y-%m-%d'))
//>>2019-01-07/2019-01-13
datastrs = ['2019-04-06 10:00:01','2019-4-8 10:00:03']
print(pd.to_datetime(datastrs))
//>>DatetimeIndex(['2019-04-06 10:00:01', '2019-04-08 10:00:03'], dtype='datetime64[ns]', freq=None)

常用時間:

類別 解釋
year
month
day
hour
minute
second
microsecond 微秒
nanosecond 納秒
date 返回日期
time 返回時間
dayofyear 年序日
weekofyear 年序周
week
dayofweek 週中的第幾天,Monday=0, Sunday=6
weekday 週中的第幾天,Monday=0, Sunday=6
weekday_name 星期
quarter 季度
days_in_month 一個月中有多少天
is_month_start 是否月初第一天
is_month_end 是否月末最後一天
is_quarter_start 是否季度第一天
is_quarter_end 是否季度最後一天
is_year_start 是否年初第一天
is_year_end 是否年末最後一天

(2)to_datetime可以處理那些被認爲是缺失值的值(None、空字符串)

idx = pd.to_datetime(datastrs + [None])
print(idx)
print(idx[2])
print(pd.isnull(idx))

結果輸出:

>>DatetimeIndex(['2019-04-06 10:00:01', '2019-04-08 10:00:03', 'NaT'], dtype='datetime64[ns]', freq=None)
>>NaT
>>[False False  True]

(3)將Str和Unicode轉化爲時間格式

這裏偷懶,直接貼圖,但是data.ORIGINAL_DUE_DATE_1[0],這是不存在的,大家理解就好:
在這裏插入圖片描述

7、strptime和strftime

(1)字符串轉換成datetime格式: strptime

用戶輸入的日期和時間是字符串,要處理日期和時間,首先必須把str轉換爲datetime。轉換方法是通過datetime.strptime()實現,需要一個日期和時間的格式化字符串:

df_data1  = pd.DataFrame(columns=['date','values'])
df_data1['date'] = ['2019-01-01','2019-01-02','2019-01-03','2019-01-04','2019-01-05']
df_data1['values'] = np.random.randn(5)
print(df_data1)
df_data1['date'] = df_data1['date'].map(lambda x:pd.datetime.strptime(x,'%Y-%m-%d'))
print(df_data1)

結果顯示:
在這裏插入圖片描述
注意轉換後的datetime是沒有時區信息的。
舉例:將分開的年月日時整合,並設置爲索引
數據集:
在這裏插入圖片描述

from datetime import datetime
# load data
def parse(x):
    return datetime.strptime(x, '%Y %m %d %H')
dataset = read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
dataset.drop('No', axis=1, inplace=True)
# manually specify column names
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
dataset.index.name = 'date'

(2)datetime變回string格式: strftime

如果已經有了datetime對象,要把它格式化爲字符串顯示給用戶,就需要轉換爲str,轉換方法是通過strftime()實現的,同樣需要一個日期和時間的格式化字符串:

df_data  = pd.DataFrame(columns=['date','values'])
df_data['date'] = pd.date_range('2019/01/01',periods=5)
df_data['values'] = np.random.randn(5)
print(df_data)

在這裏插入圖片描述
用strftime把datetime格式的時間數據轉換成string

df_data['date'] = df_data['date'].apply(lambda x:x.strftime('%Y/%m')) #datetime格式轉成str

以下是時間格式定義:

代碼  說明
%Y  4位數的年
%y  2位數的年
%m  2位數的月[01,12]
%d  2位數的日[0131]
%H  時(24小時制)[00,23]
%l  時(12小時制)[01,12]
%M  2位數的分[00,59]
%S  秒[00,61]有閏秒的存在
%w  用整數表示的星期幾[0(星期天),6]
%F  %Y-%m-%d簡寫形式例如,2017-06-27
%D  %m/%d/%y簡寫形式

想偷懶的可以直接下載代碼,另外數據也在:

https://download.csdn.net/download/im6520/12283247

主要參考:

  1. pandas處理時間序列(1):pd.Timestamp()、pd.Timedelta()、pd.datetime( )、 pd.Period()、pd.to_timestamp()、datetime.strftime()、pd.to_datetime( )、pd.to_period()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章