
全文知識(shí)架構(gòu)
分組模式及其對(duì)象

分組模式及其對(duì)象
【練一練】
請(qǐng)根據(jù)上下四分位數(shù)分割,將體重分為high、normal、low三組,統(tǒng)計(jì)身高的均值。
high = df['Weight'].quantile(0.75)
low = df['Weight'].quantile(0.25)
level = df['Weight'].mask(df['Weight']>high, 'high').mask(df['Weight']<low, 'low').mask((low<=df['Weight'])&(df['Weight']<=high), 'normal')
df.groupby(level)['Weight'].mean()
【練一練】
上一小節(jié)介紹了可以通過drop_duplicates得到具體的組類別,現(xiàn)請(qǐng)用groups屬性完成類似的功能。
gb = df.groupby(['School', 'Gender'])
gb.groups.keys()
聚合函數(shù)

聚合函數(shù)
【練一練】
請(qǐng)查閱文檔,明確all/any/mad/skew/sem/prod函數(shù)的含義。
-
all返回所有的值是否為真的結(jié)果 -
any返回所有值中是否有真值的結(jié)果 -
mad根據(jù)平均值計(jì)算絕對(duì)距離差 -
skew偏度(skewness),是統(tǒng)計(jì)數(shù)據(jù)分布偏斜方向和程度的度量 -
sem返回所請(qǐng)求軸上的平均值的無偏標(biāo)準(zhǔn)誤差 -
prod累乘
【練一練】
請(qǐng)使用【b】中的傳入字典的方法完成【a】中等價(jià)的聚合任務(wù)。
gb.agg({'Height':['sum', 'idxmax', 'skew'], 'Weight':['sum', 'idxmax', 'skew']})
【練一練】
在groupby對(duì)象中可以使用describe方法進(jìn)行統(tǒng)計(jì)信息匯總,請(qǐng)同時(shí)使用多個(gè)聚合函數(shù),完成與該方法相同的功能。
# 本來想使用傳入函數(shù)列表的方法,發(fā)現(xiàn)通過函數(shù)列表方法不支持給函數(shù)傳入?yún)?shù)
gb.agg([('count',lambda x: x.count()), ('mean', lambda x: x.mean()), ('std', lambda x: x.std()), ('min', lambda x: x.min()), ('25%',lambda x: x.quantile(0.25)),
('50%',lambda x: x.quantile(0.5)),('75%',lambda x: x.quantile(0.75))])
變換和過濾

變換和過濾
【練一練】
在groupby對(duì)象中,rank方法也是一個(gè)實(shí)用的變換函數(shù),請(qǐng)查閱它的功能并給出一個(gè)使用的例子。
# 這個(gè)操作 是 對(duì)DataFrame某列的數(shù)據(jù)進(jìn)行聚類 然后對(duì)其它列的屬于同類數(shù)據(jù)進(jìn)行數(shù)值大小排序
gb.rank(method='min', ascending=True) # method可以指定max或min,ascending可指定True or False
【練一練】
對(duì)于transform方法無法像agg一樣,通過傳入字典來對(duì)指定列使用特定的變換,如果需要在一次transform的調(diào)用中實(shí)現(xiàn)這種功能,請(qǐng)給出解決方案。
func_dict = {'Height':'max', 'Weight':'min'}
def my_transform(s, transform_dict=func_dict):
name = s.name
for key, func in transform_dict.items():
if key in [name]:
function = getattr(s, func)
return function()
gb.transform(my_transform)
跨列分組

跨列分組
【練一練】
請(qǐng)嘗試在apply傳入的自定義函數(shù)中,根據(jù)組的某些特征返回相同長度但索引不同的Series,會(huì)報(bào)錯(cuò)嗎?
def test_func(x):
if x['Weight'].shape[0] > 10:
return pd.Series([1,1],index=['a123','b12312'])
else:
return pd.Series([0,0],index=['c123123','12312d'])
gb.apply(test_func)
# 會(huì)報(bào)錯(cuò)
【練一練】
請(qǐng)嘗試在apply傳入的自定義函數(shù)中,根據(jù)組的某些特征返回相同大小但列索引不同的DataFrame,會(huì)報(bào)錯(cuò)嗎?如果只是行索引不同,會(huì)報(bào)錯(cuò)嗎?
def test_func(x):
if x['Weight'].shape[0] > 10:
return pd.DataFrame(np.ones((2,2)), index = ['a','b'], columns=pd.Index([('w','x'),('y','z')]))
else:
return pd.DataFrame(np.ones((2,2)), index = ['c','d'], columns=pd.Index([('w','d'),('y','z')]))
gb.apply(test_func)
# 以上兩種情況都不會(huì)報(bào)錯(cuò)
五、練習(xí)
Ex1:公司員工數(shù)據(jù)集
現(xiàn)有一份公司員工數(shù)據(jù)集:
- 分別只使用
query和loc選出年齡不超過四十歲且工作部門為Dairy或Bakery的男性。 - 選出員工
ID號(hào) 為奇數(shù)所在行的第1、第3和倒數(shù)第2列。 - 按照以下步驟進(jìn)行索引操作:
- 把后三列設(shè)為索引后交換內(nèi)外兩層
- 恢復(fù)中間一層
- 修改外層索引名為
Gender - 用下劃線合并兩層行索引
- 把行索引拆分為原狀態(tài)
- 修改索引名為原表名稱
- 恢復(fù)默認(rèn)索引并將列保持為原表的相對(duì)位置
# 問題1
dpt = ['Dairy', 'Bakery']
df.loc[(df.age<=40)&df.department.isin(dpt)&(df.gender=='M')].head(3)
# 問題2
df.iloc[(df.EmployeeID%2==1).values,[0,2,-2]].head()
# 問題三
# 把后三列設(shè)為索引
df_ = df.set_index(['department', 'job_title', 'gender'])
# 交換內(nèi)外兩層
df_ = df_.swaplevel(0,2, axis=0)
# 恢復(fù)中間一層
df_ = df_.reset_index(level=1, drop=False)
# 把外層索引名改為Gender
df_.rename_axis(index={'gender':'Gender'})
# 用下劃線合并兩層索引
df_.index = df_.index.map(lambda x:'_'.join(x))
# 拆分為原狀態(tài)
df_.index = df_.index.map(lambda x:tuple(x.split('_')))
# 修改索引名為原表名稱
df_ = df_.rename_axis(index=['gender','department'])
# 恢復(fù)默認(rèn)
df_ = df_.reset_index().reindex(df.columns, axis=1)