閱讀141 返回首頁    go 阿裏雲 go 技術社區[雲棲]


即學即用:Pandas入門與時間序列分析

     這篇文章是Alexander Hendorf 在PyData Florence 2017上做的報告。報告前半部分主要為初學者介紹Pandas的基本功能,如數據輸入/輸出、可視化、聚合與選擇與訪問,後半部分主要介紹如何使用Pandas進行時間序列分析,源代碼親測可用。

     PSPyData集數據分析工具的用戶和開發者,大家交流經驗、相互學習,為各領域的數據科學愛好者提供一個經驗共享平台,一起討論如何使用語言和工具應對來自數據管理、處理、分析和可視化各方麵的挑戰。

022360f2e59539d9836f7a561d66d8cbc61ff298


【Pandas起源與目標】

1. 開源Python庫

2. 實際數據分析-高速/高效/簡單

4. Wes McKinney 2008年開始編寫, 再到現在Continuum Analytics的Anaconda

5. 定期更新的穩定項目

6. 地址:https://github.com/pandas-dev/pandas

【特征】

4.數據可視化

6.類似數據庫操作

https://github.com/Koenigsweg/data-timeseries-analysis-with-pandas

1. DataSeries & DataFrame

2. I/O(輸入/輸出)

3.Data analysis &aggregation(數據分析&聚合)

4.Indexes(索引)

5. Visualization(可視化)

6.Interacting with the Data(數據交互)


29ae33aede51e9828162cd420977c6d5f01bf806

【輸入/輸出】

1.	import pandas as pd  
2.	# 讀取數據  
3.	df = pd.read_csv('raw_weather_data_aug_sep_2014/tempm.csv', header=None)  
4.	print df.head(5)   #輸出前n行  
5.	print df.tail(5)   #輸出最後n行  

b201ce1ff910cb32fd57526bb8ef5891bb40abf3

1. 使用Matplotlib,.plot() 函數

b5ed6cfa1616283f331290fe0a8113689cbc467a

【數據結構:SeriesDataFrame

Series篇】

1. 一維有標簽數組結構,可以存入任一種python的數據類型(integers, strings, floating point numbers, Python objects, etc.)

2. 序列的標簽通常稱為索引(index

930cc8712120ff8770eb48786c837edc8056d60c

數據選擇與訪問方式

1. 可以通過標簽(index選擇,也可以通過位置來選擇(從0開始)

2. 通過切片/布爾索引訪問數據,例如:


1.	series[x], series[[x, y]]  
2.	series[2], series[[2, 3]], series[2:3]  
3.	series.ix() / .iloc() / .loc()  
4.	# .ix()這種方式相當於混合了loc()和iloc()兩種方式

43c47686ef42fdad16608ca1c9b328d0e7dbe8dd

DataFrame

二維有標簽數據結構,如2維Numpy數組,關於索引,有如下規定:

2.索引可以重置或者替換

3. 類型:位置,時間戳,時間範圍,標簽…;

4.一個索引號可能會出現多次(不唯一

1. 給列命名

1.	df.columns = ['timestamp', 'temperature']  
2.	df.head(3)  

78564e92a3ac4e3cf87ac63e7a779eb17bf25f01

2. 對數據進行運算:

1.	def to_fahrenheit(celsius):  
2.	    return (celsius * 9./5.) + 32.  
3.	df['temperature'].map(to_fahrenheit)[:5]  
4.	df['temperature F'] = df['temperature'].map(to_fahrenheit)  
5.	df.head(5)  
6.	df['temperature F'] = df['temperature'].apply(lambda x: (x * 9./5.) + 32.)  
7.	df.head()  

d94a4bf2b76558d48e5950b5c28b57df7f36492d

timestamp

temperature

temperature F

0

2014-09-26T03:50:00

14.0

57.2

1

2014-08-10T05:00:00

14.0

57.2

2

2014-08-21T22:50:00

12.0

53.6

3

2014-08-17T13:20:00

16.0

60.8

4

2014-08-06T01:20:00

14.0

57.2

例3. 兩列之間也可以直接進行運算,如

1.	df['ruleoftumb'] = df['temperature F'] / df['temperature']  
2.	df.head()  

timestamp

temperature

temperature F

ruleoftumb

0

2014-09-26T03:50:00

14.0

57.2

4.085714

1

2014-08-10T05:00:00

14.0

57.2

4.085714

2

2014-08-21T22:50:00

12.0

53.6

4.466667

3

2014-08-17T13:20:00

16.0

60.8

3.800000

4

2014-08-06T01:20:00

14.0

57.2

4.085714

【修改SeriesDataFrame

Series和DataFrame的方法實際上並沒有修改原始的Series和DataFrame,而是返回一個新的Series或DataFrame,可以使用inplace參數來決定是否要用新結果替換掉原來的數據

1.	# 對列名進行重命名,rename()函數返回一個新DataFrame,  
2.	# inplace參數表示是否替換原來的DataFrame  
3.	df.rename(columns={'ruleoftumb': 'bad_rule'}, inplace=True)  
4.	df.head()  

timestamp

temperature

temperature F

bad_rule

0

2014-09-26T03:50:00

14.0

57.2

4.085714

1

2014-08-10T05:00:00

14.0

57.2

4.085714

2

2014-08-21T22:50:00

12.0

53.6

4.466667

3

2014-08-17T13:20:00

16.0

60.8

3.800000

4

2014-08-06T01:20:00

14.0

57.2

4.085714

5.	# 刪除列,inplace參數同上  
6.	df.drop('bad_rule', axis=1, inplace=True)  
7.	df.head()  

timestamp

temperature

temperature F

0

2014-09-26T03:50:00

14.0

57.2

1

2014-08-10T05:00:00

14.0

57.2

2

2014-08-21T22:50:00

12.0

53.6

3

2014-08-17T13:20:00

16.0

60.8

4

2014-08-06T01:20:00

14.0

57.2

1. describe()

4. mean(), sum(), median(),…

例1. 創建新列:

1.	# .mean()函數計算指定數據的均值  
2.	df['deviation'] = df['temperature'] - df['temperature'].mean()  
3.	df.head()  

timestamp

temperature

temperature F

deviation

0

2014-09-26T03:50:00

14.0

57.2

-1.590951

1

2014-08-10T05:00:00

14.0

57.2

-1.590951

2

2014-08-21T22:50:00

12.0

53.6

-3.590951

3

2014-08-17T13:20:00

16.0

60.8

0.409049

4

2014-08-06T01:20:00

14.0

57.2

-1.590951

例2. 用groupby()分組

1.	#按溫度分組,統計每個溫度出現的次數  
2.	df.groupby('temperature').count()  

3fbd0d00eaa5bbd6eeb8a31e27951f66035721c0

例3. 輸出指定數據統計信息

1.	# describe()方法返回數據的統計信息,不考慮空值    
2.	df['temperature'].describe(percentiles=[.1,.5,.6,.7])  

b29064c4c77758af11828a4d62c38319882582ce


NaN表示空值,可以使用drop( )移除;也可以用默認值替換或者前向填充/後向填充

1. 使用Isnull( )函數判斷是否為空

1.	df['temperature'].isnull()[2350:2357]  

69ffbb5127625db6f1f403423847fc8ce1b66322

例2. 刪除缺失值:

1.	df.dropna(inplace=True)  
2.	print df['temperature'].isnull().any()  

輸出: False ,因為已經刪除缺失值,並且用刪除之後的數據替換掉原數據,所以判斷是否存在空值時,返回False,即不存在空數據

Part2 時間序列分析(以時間戳為index的序列)

     在進行時間序列分析時,先將DataFrame的索引值由默認的數字索引變為時間戳索引

1.	#新增一列deviation,然後將默認的索引值變為時間戳索引值  
2.	df['deviation']=df['temperature']-df['temperature'].mean()  
3.	df.index=pd.to_datetime(df['timestamp'])  
4.	df.head()

9480fb06f05333c40ec7a6031b7e818031528a26

畫出DataFrame前100行,此時圖的橫坐標不再是數值索引,而是時間戳。如下:

1.	ax=df[:100].plot()  
2.	ax.axhline(df[:100]['temperature'].median(),color='r',linestyle='-')
3. plt.show()
c75c7823c286ade803790880ed8b321e588abd93

    此時,DataFrame加入weekday列和weekend

1.	# DatetimeIndex.weekday 將返回該日期是一星期中的第幾天,星期一是0,星期天是6  
2.	df['weekday'] = df.index.weekday  
3.	# isin()返回布爾值,表示df['weekday']是否在{5,6}中,  
4.	# 即判斷是否是周末  
5.	df['weekend'] = df['weekday'].isin({5, 6})  
6.	# 根據日期來分組,進行統計  
7.	df.groupby(df.index.date).count()  

6ae9b6ed4d3aa634c3deef98efcf9f823f74f07e

     那麼就可以進一步分析溫度隨著時間的變化趨勢,比如觀察每周氣溫的變化情況:

1.	# 以周為時間單位進行聚合,分析氣溫的變化情況  
2.	# 前麵已經將時間序列作為索引值,那麼這裏df.index.week返回的是一年的第幾周
3. df.groupby(df.index.week).plot()
51bd23d73a4dac459c86bfc0b68bc792396737ab

也可以分析指定時間內的溫度變化趨勢

1.	# 2014年9月氣溫變化圖(左圖)    
2.	df['2014-09']['temperature'].plot()     
3.	# 12點到16點之間的氣溫變化圖(右圖)    
4.	df[(df.index.hour > 12) & (df.index.hour <=16)]['temperature'].plot()
bba31238488117900745a317e49d123560fb5e51

時間序列重采樣(resample

      重采樣是對原樣本重新處理的一個方法,是一個對常規時間序列數據重新采樣和頻率轉換的便捷的方法,分為降采樣和升采樣,將高頻率數據聚合到低頻率數據稱為降采樣(downsampling),將低頻率轉換到高頻率稱為升采樣(upsampling)。

092a46beca4f34b5cbf196e73d661a00529ef712

首先用DataFrame進行重采樣

1.	# 按3天為時間間隔采樣  
2.	df.resample('3D').plot()  

 

d67eb0efabddcf07b75e4daf98eb2c07726d01e9

又如Series進行降采樣

1.	import random  
2.	index = pd.date_range('1/1/2016', periods=1200, freq='S') 
3.	series = pd.Series([random.randint(0,100) for p in range(1200)], index=index)  
4.	# label參數表示采用區間左邊的時間戳還是右邊的時間戳,  
5.	# closed參數表示區間是左邊閉合還是右邊閉合,和數學中[  ),(  ]區間表示形式一樣  
6.	# 一個時間戳隻能屬於一個時間段,所有時間段合並起來必須能組成原始的整個時間幀
7.	# 降采樣,從之前的1秒變為5分鍾
8.	resampled = series.resample('5T', label='right', closed='right')  
9.	print resampled 
10.	print series.resample('5T', label='left', closed='right')  
11.	print series.resample('5T', label='left', closed='left') 

5a941189f371b09196e4892bf206331171e8a4ba

升采樣,采樣頻率從5分鍾變到100秒,

1.	# 升采樣默認會引入缺失值
2.	print resampled.resample('100S')[:6]  
3.	# ffill()向前填充,即用上一個有效值填充缺失數據  
4.	# bfill()向後填充,即用下一個有效值填充缺失數據  
5.	print resampled.resample('100S').ffill()[:6]  
6.	print resampled.resample('100S').bfill()[:6]  
64be7a3242e08746a5812158d136d61cfd9bf5ef

使用statsmodels庫進一步分析時序數據

c15af75d5bade72e2212dd5f664eed18f9abdacb

1.	dtap=pd.DataFrame(mdf.groupby(mdf.index)['activity'].sum())  
2.	# 對缺失數據插值  
3.	dtap.activity.interpolate(inplace=True)  
4.	res=sm.tsa.seasonal_decompose(dtap.activity)  
5.	resplot=res.plot()  
6.	resplot.set_size_inches(15,15)
輸出:
79e9e5f8824796a6c158ca64d447d0caa5c26d42

安利一個會議:EuroPython 2017, 歐洲最大的Python會議,歡迎參加。

282abf14ff9ffb045daed98b73e346f9a31ea2d4


作者介紹

9dc3fab8483a5e5d64c3a722abb050d8fd0b8293


以上為譯文

文章原標題《Introduction to Pandas and Time Series Analysis》,作者:Alexander C. S. Hendorf,譯者:李烽 審校:

文章為簡譯,更為詳細的內容,請查看原文

PS:中文譯製PDF版食用更佳,可讀性更強,見附件。



最後更新:2017-05-15 13:01:26

  上一篇:go  Java程序員的十個調試技巧
  下一篇:go  Python 3 學習之路 (1)變量,用戶交互,if else , while ,for