數據類型object與category比較
category數據類型
官方文檔是這樣描述的:
Categoricals 是 pandas 的一種數據類型,對應着被統計的變量。
1.Categoricals 是由固定的且有限數量的變量組成的。比如:性別、社會階層、血型、國籍、觀察時段、贊美程度等等。
2.與其它被統計的變量相比,categorical 類型的數據可以具有特定的順序——比如:按程度來設定,“強烈同意”與“同意”,“首次觀察”與“二次觀察”,但是不能做按數值來進行排序操作
(比如:sort_by 之類的,換句話說,categorical 的順序是創建時手工設定的,是靜態的)
3.類型數據的每一個元素的值要么是預設好的類型中的某一個,要么是空值(np.nan)。
創建 Categorical 數據
轉化創建[object=>category]
用一段代碼從不同角度來展現一下 categorical 類型的數據。
# 用一組數據記錄各自的得分情況 import pandas as pd, numpy as np players=['Garsol','Hardon','Bill'] scores=[22,34,12,] teams=['West','West','East'] df=pd.DataFrame({'player':players,'score':scores,'team':teams}) print("df.player.dtype:",df.player.dtype) df
把team字段轉為category數據類型
df["team"].astype('category')
colors = pd.DataFrame(['Garsol','Hardon','Bill'],columns=['name']) pd.factorize(colors['name'])
這個返回值是個tuple,內有兩個元素。
動態添加category數據類型
d=pd.Series(scores).describe() score_ranges=[d['min']-1,d['mean'],d['max']+1] score_labels=['Role','Star'] # 用pd.cut(ori_data, bins, labels) 方法 # 以 bins 設定的畫界點來將 ori_data 歸類,然后用 labels 中對應的 label 來作為分類名 df['level']=pd.cut(df['score'],score_ranges,labels=score_labels) df
df['team']
df['level']
直接創建 category類型數據
roles=pd.Categorical(['Role','xxx','Star'],categories=['Role', 'Star'])
roles
構造方法中第二個參數是指定了實例中可以包含的元素,在第一個參數中的元素如果不在 categories 中,就會被轉成NaN。
df=pd.DataFrame({'players':['Garsol','Hardon','Bill']}) df['level']=roles df['level']
內存占用分析
import pandas as pd colors = pd.Series(['periwinkle','mint green','burnt orange','periwinkle','burnt orange','rose','rose','mint green','rose','navy']) print('colors type:',colors.dtype,'===>','memory_usage():',colors.memory_usage(index=False, deep=True)) colors=colors.astype('category') print('colors type:',colors.dtype,'===>','memory_usage():',colors.memory_usage(index=False, deep=True)) colors=colors.astype('category').cat.codes print('colors type:',colors.dtype,'===>','memory_usage():',colors.memory_usage(index=False, deep=True))

import matplotlib.pyplot as plt plt.rcParams['font.sans-serif']=['Microsoft YaHei'] colors = pd.Series(['periwinkle','mint green','burnt orange','periwinkle','burnt orange','rose','rose','mint green','rose','navy']) x=range(20) y1=[] y2=[] y3=[] for i in x: colorss=colors.repeat(i) y1.append(colorss.memory_usage(index=False, deep=True)) colorss=colorss.astype('category') y2.append(colorss.memory_usage(index=False, deep=True)) colorss=colorss.cat.codes y3.append(colorss.memory_usage(index=False, deep=True)) plt.plot(x,y1,label='object') plt.plot(x,y2,label='category') plt.plot(x,y3,label='int') # x軸標簽 plt.xlabel('數據量') # y軸標簽 plt.ylabel('內存占用') # 可視化圖標題 plt.title('object-category-int數據類型研究') # 顯示圖例 plt.legend() # 顯示圖形 plt.show() print('y1',y1) print('y2',y2) print('y3',y3)
內存占用區別:
1.object所占用的內存則是一個常數乘以數據的長度。這個斜率為很大。
2.int類型基本一個常數乘以數據的長度。這個初始值為0且為10(這里int16)
3.初始值80增速也很慢最終增速為同(2)
其實我們能猜測到category存儲的方式,數據用int存儲然后再維持一個從int到category的映射。
所以Category內存是成比例的,如果數據集的數據量很大,但不重復分類(unique)值很少的情況下,那么Category的內存占用可以大大的節約內存。
計算效率分析
除了占用內存節省外,另一個額外的好處是計算效率有了很大的提升。
因為對於Category類型的Series,str字符的操作發生在.cat.categories的非重復值上,而並非原Series上的所有元素上。
也就是說對於每個非重復值都只做一次操作,然后再向與非重復值同類的值映射過去。
對於Category的數據類型,可以使用accessor的cat對象,以及相應的屬性和方法來操作Category數據。
colors = pd.Series(['periwinkle','mint green','burnt orange','periwinkle','burnt orange','rose','rose','mint green','rose','navy']) colorss=colors.repeat(10001) colorss.astype('category').cat.categories
實際上,對於開始的整數類型映射,我們可以先通過reorder_categories進行重新排序,然后再使用cat.codes來實現對整數的映射,來達到同樣的效果。
mapper={'Garsol':0,'Hardon':1,'Bill':2} names= pd.DataFrame(['Garsol','Hardon','Bill'],columns=['name']) colors
names['alias']=names.name.astype('category').cat.codes names
names['alias']=names.astype('category').name.cat.reorder_categories(mapper).cat.codes names
names.astype('category').name.cat返回的是 pandas.core.arrays.categorical.CategoricalAccessor數據類型
[i for i in dir(colors.astype('category').name.cat) if not i.startswith('_')] 輸出如下: ['add_categories', 'as_ordered', 'as_unordered', 'categorical', 'categories', 'codes', 'index', 'name', 'ordered', 'remove_categories', 'remove_unused_categories', 'rename_categories', 'reorder_categories', 'set_categories']
完結!!!