pandas 數據類型研究(三)數據類型object與category


數據類型object與category比較

category數據類型

官方文檔是這樣描述的:

Categoricals 是 pandas 的一種數據類型,對應着被統計的變量。

  1.Categoricals 是由固定的且有限數量的變量組成的。比如:性別、社會階層、血型、國籍、觀察時段、贊美程度等等。

  2.與其它被統計的變量相比,categorical 類型的數據可以具有特定的順序——比如:按程度來設定,“強烈同意”與“同意”,“首次觀察”與“二次觀察”,但是不能做按數值來進行排序操作

                                          (比如:sort_by 之類的,換句話說,categorical 的順序是創建時手工設定的,是靜態的)

  3.類型數據的每一個元素的值要么是預設好的類型中的某一個,要么是空值(np.nan)。

  4.categorical 實例的內部是由類型名字集合和一個整數組成的數組構成的,后者標明了類型集合真正的值。順序是由預設好的類型集合來決定的,而不是按照類型集合中各個元素的字母順序排序的。

創建 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')

df.team 的變量類型變成了 category
  相似用法factorize
colors = pd.DataFrame(['Garsol','Hardon','Bill'],columns=['name'])
pd.factorize(colors['name'])

這個返回值是個tuple,內有兩個元素。

 

 

 

 

動態添加category數據類型

如按照得分來划分,將高於平均分的划為 Star,低於平均分的划為 Role。計算過程就應該是這樣:
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)
object-category-int數據類型研究

 

 內存占用區別:

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']

 完結!!!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM