详解python pandas库中的groupby函数

groupby函数

  • pandas 的 groupby 方法是一个强大的工具,用于对数据进行分组操作。它允许你根据某些条件对数据进行分组,然后对每个分组应用聚合函数、转换函数或过滤函数。以下是 groupby 的一些常见用法和示例。
  • 基本用法:
      很多同学其实都知道有groupby这个函数,但是很多时候都是知其然而不知其所以然。
    今天我们就来一起探究以下
import pandas as pd

# 创建一个示例 DataFrame
data = {
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Values': [10, 20, 30, 40, 50, 60]
}
df = pd.DataFrame(data)

# 按 'Category' 列分组
grouped = df.groupby('Category')

# grouped 不是一个数组,而是一个 DataFrameGroupBy 对象
print(type(grouped))  # <class 'pandas.core.groupby.generic.DataFrameGroupBy'>

# 迭代分组对象,查看每个分组及其数据
for name, group in grouped:
    print(f"Group name: {name}")
    print(group)

'''
这是输出
Group name: A
  Category  Values
0        A      10
2        A      30
4        A      50
Group name: B
  Category  Values
1        B      20
3        B      40
5        B      60

'''

grouped 不是一个数组,而是一个 pandas.core.groupby.DataFrameGroupBy 对象。这个对象包含了关于如何分组以及对每个分组进行操作的信息。你可以将它看作是一个分组数据的抽象表示,而不是一个实际的数据结构如数组。

下面是一些关于 grouped 对象的关键点:

grouped 对象的性质

  1. 分组键(Grouping Keys):grouped 对象包含了用于分组的键(列)。
  2. 分组迭代器(Group Iterator):你可以迭代 grouped 对象来访问每个分组及其对应的数据。
  3. 分组操作(Group Operations):你可以对 grouped 对象应用各种聚合、转换和过滤操作。

由上面代码我们可以看出来,可以用(name,group)去迭代该grouped对象,得到的name其实就是分组依据中独特的一项!!!然后group就是通过该分组依据分出的各个组(也就是说,每个组对应于我们的分组依据都是一样的,比如说上面那个,第一组的name是A,就是因为我们就是按照Catagory分的组)

我们也可以只访问单个分组:
你可以通过分组键直接访问某个特定的分组:

group_a = grouped.get_group('A')
print(group_a)
输出结果:

  Category  Values
0        A      10
2        A      30
4        A      50
  • 通过上面的例子我们也知道了groupby后的函数到底是什么东西。这是远远不够的,我们还需要直到它能干什么。
  1. 聚合操作,我们刚才也看到了,我们groupby后得到的对象里面其实就是一个个类似于一个新的dataframe(只不过我们刚才用于分组的那一列元素都相同)
data = {
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Values': [10, 20, 30, 40, 50, 60],
    'values2': [100, 200, 300, 400, 500, 600]
}
df = pd.DataFrame(data)
print(df)
grouped = df.groupby('Category')
print(grouped.mean())#聚合操作

'''
输出结果
          Values  values2
Category                 
A           30.0    300.0
B           40.0    400.0
可见返回了一个新的dataframe,刚才的分类依据变成了新的index,然后columns与原来是一样的,只不过里面的数被各个组的该column下的mean()所替代了
'''

类似的聚合操作:

1求和 (sum):
  df.groupby(‘Category’).sum()
2平均值 (mean):
  df.groupby(‘Category’).mean()
3计数 (count):
  df.groupby(‘Category’).count()
4最大值 (max) 和最小值 (min):
  df.groupby(‘Category’).max()
  df.groupby(‘Category’).min()

  1. 使用apply方法
    相当于对每一个dataframe进行操作
# 对每个分组应用自定义函数
data = {
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Values': [10, 20, 30, 40, 50, 60],
    'values2': [100, 200, 300, 400, 500, 600]
}
df = pd.DataFrame(data)
grouped = df.groupby('Category')
result = grouped.apply(lambda x: x.sum(),include_groups=False)
print(result)
'''
结果:(和上面聚合函数的原理基本相同)
          Values  values2
Category                 
A             90      900
B            120     1200

'''

3.使用transform方法
  tramsform是作用于每个函数的每一个值,最后返回一个总的dataframe(且与分组前的位置相同),这时候很多同学都会有疑问,那transform有什么用呢?其实吧,如果只是加减常数,确实没有什么用,都是如果是对其进行有关其分组的处理,那就有作用了,比如下面:
  假设我们有一个包含员工信息的DataFrame,我们想要根据部门对员工的薪水进行标准化处理。标准化处理意味着我们想要将每个员工的薪水转换为相对于他们部门平均薪水的偏差。这里,我们可以使用groupby和transform来实现。

其实前面学的apply函数,也可以对每个元素进行操作,它与tramsform最大的不同就是他的结果是已经分好组的,而tramsform即使数据改变了,那个数据仍然位置与分组前一样,这是她们最大的区别,大家根据要求各取所需即可。

import pandas as pd

# 创建一个示例DataFrame
df = pd.DataFrame({
    'Department': ['HR', 'IT', 'HR', 'IT', 'IT', 'HR', 'IT', 'HR'],
    'Employee': ['Alice', 'Bob', 'Cindy', 'David', 'Eva', 'Frank', 'Grace', 'Helen'],
    'Salary': [50000, 60000, 54000, 62000, 61000, 52000, 63000, 51000]
})

# 使用groupby和transform计算每个员工薪水相对于部门平均薪水的偏差
df['Salary Deviation'] = df.groupby('Department')['Salary'].transform(lambda x: x - x.mean())

print(df)
'''
  Department Employee  Salary  Salary Deviation
0        HR    Alice   50000          -4000.0
1        IT      Bob   60000           0.0
2        HR   Cindy   54000           2000.0
3        IT   David   62000           2000.0
4        IT     Eva   61000           1000.0
5        HR   Frank   52000          -8000.0
6        IT   Grace   63000           3000.0
7        HR   Helen   51000          -9000.0
'''
可以见得虽然说与原来的位置相同,都是mean用的都是各自分组的,在特定的情形中还是很有用的

4.使用filter方法过滤掉不要的组

df_filtered = df.groupby('Category').filter(lambda x: x['Values'].mean() > 30)
#过滤掉了平均值小于等于30的组

5.可以对分组后的各个组进行size和describe操作,size提供各个组的元素数量,describe可以对各个组的各种信息进行汇总,当然也可以通过xx.get_group(‘A’).describe(),可能更加直观

6.还有一个超好用我超喜欢的函数就是aggregate(缩写agg),你可以对同一列或多个列使用不同的聚合函数。例如,可以同时计算均值和标准差。可以传入多个聚合函数,甚至可以传入自定义的函数,以实现更复杂的计算。

#可以传入自定义函数,绝了!!!
def calculate_range(x):
    return x.max() - x.min()
data = {
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Values': [10, 20, 30, 40, 50, 60],
    'values2': [100, 200, 300, 400, 500, 600],
    'valus3': [1000, 2000, 3000, 4000, 5000, 6000]
}
df = pd.DataFrame(data)
grouped = df.groupby('Category')
print(grouped['Values'].agg(['mean', 'std',calculate_range]))
print(grouped.agg({'Values': ['mean','std'], 'values2': ['mean','std'], 'valus3': ['mean','std']}))
#如果没有指明哪一列,或者想同时对多列进行操作,可以传入字典

'''
          mean   std  calculate_range
Category                             
A         30.0  20.0               40
B         40.0  20.0               40
         Values       values2         valus3        
           mean   std    mean    std    mean     std
Category                                            
A          30.0  20.0   300.0  200.0  3000.0  2000.0
B          40.0  20.0   400.0  200.0  4000.0  2000.0
'''

以下是一些常用的可以传入agg的聚合函数
mean:计算均值。
sum:计算总和。
count:计算元素数量(非缺失值的数量)。
min:计算最小值。
max:计算最大值。
std:计算标准差。
var:计算方差。
median:计算中位数。
first:返回每组的第一个值。
last:返回每组的最后一个值。
quantile:计算分位数,可以指定分位数的百分比。
prod:计算乘积。
agg:你也可以传入其他任意自定义函数。

  好啦,今天关于groupby的内容就讲解到这里了,后面如果有一些新的发现也会继续补充的!编程是一种创造的艺术,代码是你的画布,勇敢去编织出你的梦想吧!每一次调试都是进步的机会,坚持下去,未来的你一定会感谢现在努力的自己!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值