作者:SeanCheney Python愛好者社區專欄作者
簡書專欄:https://www.jianshu.com/u/130f76596b02
前文傳送門:
【翻譯】《利用Python進行數據分析·第2版》第1章 準備工作
【翻譯】《利用Python進行數據分析·第2版》第2章(上)Python語法基礎,IPython和Jupyter
【翻譯】《利用Python進行數據分析·第2版》第2章(中)Python語法基礎,IPython和Jupyter
【翻譯】《利用Python進行數據分析·第2版》第2章(下)Python語法基礎,IPython和Jupyter
【翻譯】《利用Python進行數據分析·第2版》第3章(上)Python的數據結構、函數和文件
【翻譯】《利用Python進行數據分析·第2版》第3章(中)Python的數據結構、函數和文件
【翻譯】《利用Python進行數據分析·第2版》第3章(下)Python的數據結構、函數和文件
【翻譯】《利用Python進行數據分析·第2版》第4章(上)NumPy基礎:數組和矢量計算
【翻譯】《利用Python進行數據分析·第2版》第4章(中)NumPy基礎:數組和矢量計算
【翻譯】《利用Python進行數據分析·第2版》第4章(下)NumPy基礎:數組和矢量計算
【翻譯】《利用Python進行數據分析·第2版》第5章(上)pandas入門
【翻譯】《利用Python進行數據分析·第2版》第5章(中)pandas入門
【翻譯】《利用Python進行數據分析·第2版》第5章(下)pandas入門
【翻譯】《利用Python進行數據分析·第2版》第6章(上) 數據加載、存儲與文件格式
【翻譯】《利用Python進行數據分析·第2版》第6章(中) 數據加載、存儲與文件格式
【翻譯】《利用Python進行數據分析·第2版》第6章(下) 數據加載、存儲與文件格式
【翻譯】《利用Python進行數據分析·第2版》第7章(上)數據清洗和準備
【翻譯】《利用Python進行數據分析·第2版》第7章(中) 數據清洗和準備
【翻譯】《利用Python進行數據分析·第2版》第7章(下) 數據清洗和準備
【翻譯】《利用Python進行數據分析·第2版》第8章(上) 數據規整:聚合、合併和重塑
【翻譯】《利用Python進行數據分析·第2版》第8章(中) 數據規整:聚合、合併和重塑
【翻譯】《利用Python進行數據分析·第2版》第9章(上) 繪圖和可視化
【翻譯】《利用Python進行數據分析·第2版》第9章(中) 繪圖和可視化
【翻譯】《利用Python進行數據分析·第2版》第9章(下) 繪圖和可視化
【翻譯】《利用Python進行數據分析·第2版》第10章(上) 數據聚合與分組運算
【翻譯】《利用Python進行數據分析·第2版》第10章(中) 數據聚合與分組運算
【翻譯】《利用Python進行數據分析·第2版》第10章(下) 數據聚合與分組運算
【翻譯】《利用Python進行數據分析·第2版》第11章(上) 時間序列
【翻譯】《利用Python進行數據分析·第2版》第11章(中) 時間序列
【翻譯】《利用Python進行數據分析·第2版》第11章(中二) 時間序列
【翻譯】《利用Python進行數據分析·第2版》第11章(下) 時間序列
【翻譯】《利用Python進行數據分析·第2版》第12章(上) pandas高級應用
用分類進行計算
與非編碼版本(比如字符串數組)相比,使用pandas的Categorical有些類似。某些pandas組件,比如groupby函數,更適合進行分類。還有一些函數可以使用有序標誌位。
來看一些隨機的數值數據,使用pandas.qcut面元函數。它會返回pandas.Categorical,我們之前使用過pandas.cut,但沒解釋分類是如何工作的:
In [41]: np.random.seed(12345)In [42]: draws = np.random.randn(1000)In [43]: draws[:5]Out[43]: array([-0.2047, 0.4789, -0.5194, -0.5557, 1.9658])
計算這個數據的分位面元,提取一些統計信息:
In [44]: bins = pd.qcut(draws, 4)In [45]: binsOut[45]: [(-0.684, -0.0101], (-0.0101, 0.63], (-0.684, -0.0101], (-0.684, -0.0101], (0.63, 3.928], ..., (-0.0101, 0.63], (-0.684, -0.0101], (-2.95, -0.684], (-0.0101, 0.63], (0.63, 3.928]]Length: 1000Categories (4, interval[float64]): [(-2.95, -0.684] < (-0.684, -0.0101] < (-0.0101, 0.63] < (0.63, 3.928]]
雖然有用,確切的樣本分位數與分位的名稱相比,不利於生成匯總。我們可以使用labels參數qcut,實現目的:
In [46]: bins = pd.qcut(draws, 4, labels=['Q1', 'Q2', 'Q3', 'Q4'])In [47]: binsOut[47]: [Q2, Q3, Q2, Q2, Q4, ..., Q3, Q2, Q1, Q3, Q4]Length: 1000Categories (4, object): [Q1 < Q2 < Q3 < Q4]In [48]: bins.codes[:10]Out[48]: array([1, 2, 1, 1, 3, 3, 2, 2, 3, 3], dtype=int8)
加上標籤的面元分類不包含數據面元邊界的信息,因此可以使用groupby提取一些匯總信息:
In [49]: bins = pd.Series(bins, name='quartile')In [50]: results = (pd.Series(draws) ....: .groupby(bins) ....: .agg(['count', 'min', 'max']) ....: .reset_index())In [51]: resultsOut[51]: quartile count min max0 Q1 250 -2.949343 -0.6854841 Q2 250 -0.683066 -0.0101152 Q3 250 -0.010032 0.6288943 Q4 250 0.634238 3.927528
分位數列保存了原始的面元分類信息,包括排序:
In [52]: results['quartile']Out[52]:0 Q11 Q22 Q33 Q4Name: quartile, dtype: categoryCategories (4, object): [Q1 < Q2 < Q3 < Q4]
用分類提高性能如果你是在一個特定數據集上做大量分析,將其轉換為分類可以極大地提高效率。DataFrame列的分類使用的內存通常少的多。來看一些包含一千萬元素的Series,和一些不同的分類:
In [53]: N = 10000000In [54]: draws = pd.Series(np.random.randn(N))In [55]: labels = pd.Series(['foo', 'bar', 'baz', 'qux'] * (N // 4))
現在,將標籤轉換為分類:
In [56]: categories = labels.astype('category')
這時,可以看到標籤使用的內存遠比分類多:
In [57]: labels.memory_usage()Out[57]: 80000080In [58]: categories.memory_usage()Out[58]: 10000272
轉換為分類不是沒有代價的,但這是一次性的代價:
In [59]: %time _ = labels.astype('category')CPU times: user 490 ms, sys: 240 ms, total: 730 msWall time: 726 ms
GroupBy操作明顯比分類快,是因為底層的算法使用整數編碼數組,而不是字符串數組。
分類方法包含分類數據的Series有一些特殊的方法,類似於Series.str字符串方法。它還提供了方便的分類和編碼的使用方法。看下面的Series:
In [60]: s = pd.Series(['a', 'b', 'c', 'd'] * 2)In [61]: cat_s = s.astype('category')In [62]: cat_sOut[62]: 0 a1 b2 c3 d4 a5 b6 c7 ddtype: categoryCategories (4, object): [a, b, c, d]
特別的cat屬性提供了分類方法的入口:
In [63]: cat_s.cat.codesOut[63]: 0 01 12 23 34 05 16 27 3dtype: int8In [64]: cat_s.cat.categoriesOut[64]: Index(['a', 'b', 'c', 'd'], dtype='object')
假設我們知道這個數據的實際分類集,超出了數據中的四個值。我們可以使用set_categories方法改變它們:
In [65]: actual_categories = ['a', 'b', 'c', 'd', 'e']In [66]: cat_s2 = cat_s.cat.set_categories(actual_categories)In [67]: cat_s2Out[67]: 0 a1 b2 c3 d4 a5 b6 c7 ddtype: categoryCategories (5, object): [a, b, c, d, e]
雖然數據看起來沒變,新的分類將反映在它們的操作中。例如,如果有的話,value_counts表示分類:
In [68]: cat_s.value_counts()Out[68]: d 2c 2b 2a 2dtype: int64In [69]: cat_s2.value_counts()Out[69]: d 2c 2b 2a 2e 0dtype: int64
在打數據集中,分類經常作為節省內存和高性能的便捷工具。過濾完大DataFrame或Series之後,許多分類可能不會出現在數據中。我們可以使用remove_unused_categories方法刪除沒看到的分類:
In [70]: cat_s3 = cat_s[cat_s.isin(['a', 'b'])]In [71]: cat_s3Out[71]: 0 a1 b4 a5 bdtype: categoryCategories (4, object): [a, b, c, d]In [72]: cat_s3.cat.remove_unused_categories()Out[72]: 0 a1 b4 a5 bdtype: categoryCategories (2, object): [a, b]
表12-1列出了可用的分類方法。
表12-1 pandas的Series的分類方法
為建模創建虛擬變量當你使用統計或機器學習工具時,通常會將分類數據轉換為虛擬變量,也稱為one-hot編碼。這包括創建一個不同類別的列的DataFrame;這些列包含給定分類的1s,其它為0。
看前面的例子:
In [73]: cat_s = pd.Series(['a', 'b', 'c', 'd'] * 2, dtype='category')
前面的第7章提到過,pandas.get_dummies函數可以轉換這個以為分類數據為包含虛擬變量的DataFrame:
In [74]: pd.get_dummies(cat_s)Out[74]: a b c d0 1 0 0 01 0 1 0 02 0 0 1 03 0 0 0 14 1 0 0 05 0 1 0 06 0 0 1 07 0 0 0 1
讚賞作者
好課推薦,下圖掃碼即可免費學習
Python愛好者社區歷史文章大合集:
Python愛好者社區歷史文章列表(每周append更新一次)
福利:文末掃碼立刻關注公眾號,「Python愛好者社區」,開始學習Python課程:
關注後在公眾號內回復「課程」即可獲取:
小編的Python入門視頻課程!!!
崔老師爬蟲實戰案例免費學習視頻。
丘老師數據科學入門指導免費學習視頻。
陳老師數據分析報告製作免費學習視頻。
玩轉大數據分析!Spark2.X+Python 精華實戰課程免費學習視頻。
丘老師Python網絡爬蟲實戰免費學習視頻。