可以通过agg()或aggregate()进行更复杂的操作,如一次计算多个统计值。
df = pd.read_csv("data/employees.csv") # 读取员工数据
# 按department_id分组,计算salary的最小值,中位数,最大值
print(df.groupby("department_id")["salary"].agg(["min", "median", "max"]))
# min median max
# department_id
# 10.0 4400.0 4400.0 4400.0
# 20.0 6000.0 9500.0 13000.0
# 30.0 2500.0 2850.0 11000.0
# 40.0 6500.0 6500.0 6500.0
# 50.0 2100.0 3100.0 8200.0
多个列计算不同的统计值
也可以在agg()中传入字典,对多个列计算不同的统计值。
df = pd.read_csv("data/employees.csv") # 读取员工数据
# 按department_id分组,统计job_id的种类数,commission_pct的平均值
print(df.groupby("department_id").agg({"job_id": "nunique", "commission_pct": "mean"}))
# job_id commission_pct
# department_id
# 10.0 1 NaN
# 20.0 2 NaN
# 30.0 2 NaN
# 40.0 1 NaN
# 50.0 3 NaN
重命名统计值
可以在agg()后通过rename()对统计后的列重命名。
f = pd.read_csv("data/employees.csv") # 读取员工数据
# 按department_id分组,统计job_id的种类数,commission_pct的平均值
print(
df.groupby("department_id")
.agg(
{"job_id": "nunique", "commission_pct": "mean"},
)
.rename(
columns={"job_id": "工种数", "commission_pct": "佣金比例平均值"},
)
)
# 工种数 佣金比例平均值
# department_id
# 10.0 1 NaN
# 20.0 2 NaN
# 30.0 2 NaN
# 40.0 1 NaN
# 50.0 3 NaN
自定义函数
可以向agg()中传入自定义函数进行计算。
df = pd.read_csv("data/employees.csv") # 读取员工数据
def f(x):
"""统计每个部门员工last_name的首字母"""
result = set()
for i in x:
result.add(i[0])
return result
print(df.groupby("department_id")["last_name"].agg(f))
# department_id
# 10.0 {W}
# 20.0 {F, H}
# 30.0 {B, T, R, C, K, H}
# 40.0 {M}
# 50.0 {O, E, K, S, W, L, P, D, C, V, B, T, M, J, F, ...
4. 分组转换
聚合操作返回的是对组内全量数据缩减过的结果,而转换操作会返回一个新的全量数据。数据经过转换之后,其形状与原来的输入数据是一样的。
通过transform()将每一组的样本数据减去各组的均值,实现数据标准化
df = pd.read_csv("data/employees.csv") # 读取员工数据
print(df.groupby("department_id")["salary"].transform(lambda x: x - x.mean()))
过transform()按分组使用平均值填充缺失值
df = pd.read_csv("data/employees.csv") # 读取员工数据
na_index = pd.Series(df.index.tolist()).sample(30) # 随机挑选30条数据
df.loc[na_index, "salary"] = pd.NA # 将这30条数据的salary设置为缺失值
print(df.groupby("department_id")["salary"].agg(["size", "count"])) # 查看每组数据总数与非空数据数
def fill_missing(x):
# 使用平均值填充,如果平均值也为NaN,用0填充
if np.isnan(x.mean()):
return 0
return x.fillna(x.mean())
df["salary"] = df.groupby("department_id")["salary"].transform(fill_missing)
print(df.groupby("department_id")["salary"].agg(["size", "count"])) # 查看每组数据总数与非空数据数
5. 分组过滤
过滤操作可以让我们按照分组的属性丢弃若干数据。
例如,我们可能只需要保留commission_pct不包含空值的分组的数据。
commission_pct_filter = df.groupby("department_id").filter(
lambda x: x["commission_pct"].notnull().all()
) # 按department_id分组,过滤掉commission_pct包含空值的分组
print(commission_pct_filter)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END











请登录后查看评论内容