
全文知识架构
分组模式及其对象

分组模式及其对象
【练一练】
请根据上下四分位数分割,将体重分为high、normal、low三组,统计身高的均值。
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()
【练一练】
上一小节介绍了可以通过drop_duplicates得到具体的组类别,现请用groups属性完成类似的功能。
gb = df.groupby(['School', 'Gender'])
gb.groups.keys()
聚合函数

聚合函数
【练一练】
请查阅文档,明确all/any/mad/skew/sem/prod函数的含义。
-
all返回所有的值是否为真的结果 -
any返回所有值中是否有真值的结果 -
mad根据平均值计算绝对距离差 -
skew偏度(skewness),是统计数据分布偏斜方向和程度的度量 -
sem返回所请求轴上的平均值的无偏标准误差 -
prod累乘
【练一练】
请使用【b】中的传入字典的方法完成【a】中等价的聚合任务。
gb.agg({'Height':['sum', 'idxmax', 'skew'], 'Weight':['sum', 'idxmax', 'skew']})
【练一练】
在groupby对象中可以使用describe方法进行统计信息汇总,请同时使用多个聚合函数,完成与该方法相同的功能。
# 本来想使用传入函数列表的方法,发现通过函数列表方法不支持给函数传入参数
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对象中,rank方法也是一个实用的变换函数,请查阅它的功能并给出一个使用的例子。
# 这个操作 是 对DataFrame某列的数据进行聚类 然后对其它列的属于同类数据进行数值大小排序
gb.rank(method='min', ascending=True) # method可以指定max或min,ascending可指定True or False
【练一练】
对于transform方法无法像agg一样,通过传入字典来对指定列使用特定的变换,如果需要在一次transform的调用中实现这种功能,请给出解决方案。
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)
跨列分组

跨列分组
【练一练】
请尝试在apply传入的自定义函数中,根据组的某些特征返回相同长度但索引不同的Series,会报错吗?
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)
# 会报错
【练一练】
请尝试在apply传入的自定义函数中,根据组的某些特征返回相同大小但列索引不同的DataFrame,会报错吗?如果只是行索引不同,会报错吗?
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)
# 以上两种情况都不会报错
五、练习
Ex1:公司员工数据集
现有一份公司员工数据集:
- 分别只使用
query和loc选出年龄不超过四十岁且工作部门为Dairy或Bakery的男性。 - 选出员工
ID号 为奇数所在行的第1、第3和倒数第2列。 - 按照以下步骤进行索引操作:
- 把后三列设为索引后交换内外两层
- 恢复中间一层
- 修改外层索引名为
Gender - 用下划线合并两层行索引
- 把行索引拆分为原状态
- 修改索引名为原表名称
- 恢复默认索引并将列保持为原表的相对位置
# 问题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()
# 问题三
# 把后三列设为索引
df_ = df.set_index(['department', 'job_title', 'gender'])
# 交换内外两层
df_ = df_.swaplevel(0,2, axis=0)
# 恢复中间一层
df_ = df_.reset_index(level=1, drop=False)
# 把外层索引名改为Gender
df_.rename_axis(index={'gender':'Gender'})
# 用下划线合并两层索引
df_.index = df_.index.map(lambda x:'_'.join(x))
# 拆分为原状态
df_.index = df_.index.map(lambda x:tuple(x.split('_')))
# 修改索引名为原表名称
df_ = df_.rename_axis(index=['gender','department'])
# 恢复默认
df_ = df_.reset_index().reindex(df.columns, axis=1)