Pandas GroupBy 分组操作及获取分组详解

Pandas GroupBy 分组操作及获取分组详解

参考:pandas groupby get groups

Pandas是Python中用于数据分析和处理的强大库,其中GroupBy操作是一个非常重要的功能。本文将详细介绍Pandas中的GroupBy操作以及如何获取分组结果,帮助读者更好地理解和使用这一功能。

1. GroupBy的基本概念

GroupBy操作允许我们将数据按照某个或某些列进行分组,然后对每个分组进行聚合操作。这在数据分析中非常有用,可以帮助我们快速了解数据的分布和特征。

让我们从一个简单的例子开始:

import pandas as pd

# 创建一个示例DataFrame
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'age': [25, 30, 35, 28, 32],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

# 按城市分组
grouped = df.groupby('city')

# 打印分组对象
print(grouped)

Output:

Pandas GroupBy 分组操作及获取分组详解

在这个例子中,我们创建了一个包含姓名、年龄、城市和薪资信息的DataFrame,然后使用groupby()方法按城市进行分组。grouped对象是一个DataFrameGroupBy对象,它包含了分组的信息,但还没有进行任何聚合操作。

2. 获取分组信息

2.1 使用groups属性

GroupBy对象有一个groups属性,它返回一个字典,其中键是分组的唯一值,值是对应的行索引。

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

grouped = df.groupby('city')
groups = grouped.groups

print(groups)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个示例将打印出每个城市对应的行索引。这对于了解每个分组包含哪些数据非常有用。

2.2 使用get_group()方法

如果我们想获取特定分组的数据,可以使用get_group()方法:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

grouped = df.groupby('city')
london_group = grouped.get_group('London')

print(london_group)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子将返回一个新的DataFrame,只包含城市为London的数据。

3. 对分组进行聚合操作

GroupBy对象支持多种聚合操作,如sum()、mean()、count()等。

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

grouped = df.groupby('city')

# 计算每个城市的平均薪资
avg_salary = grouped['salary'].mean()

print(avg_salary)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子计算了每个城市的平均薪资。

4. 多列分组

我们也可以按多个列进行分组:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'department': ['IT', 'HR', 'Finance', 'IT', 'HR'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

grouped = df.groupby(['city', 'department'])
avg_salary = grouped['salary'].mean()

print(avg_salary)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子按城市和部门进行分组,然后计算每个组合的平均薪资。

5. 应用自定义函数

我们可以使用apply()方法对每个分组应用自定义函数:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

def salary_range(group):
    return pd.Series({
        'min_salary': group['salary'].min(),
        'max_salary': group['salary'].max(),
        'range': group['salary'].max() - group['salary'].min()
    })

result = df.groupby('city').apply(salary_range)

print(result)

这个例子定义了一个函数来计算每个城市的最低薪资、最高薪资和薪资范围。

6. 分组转换

使用transform()方法,我们可以对每个分组应用一个函数,并将结果广播回原始DataFrame的形状:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

df['salary_rank'] = df.groupby('city')['salary'].transform(lambda x: x.rank(method='dense'))

print(df)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子为每个城市内的薪资进行排名。

7. 分组迭代

我们可以直接迭代GroupBy对象来访问每个分组:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

for name, group in df.groupby('city'):
    print(f"City: {name}")
    print(group)
    print("\n")

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子将遍历每个城市的分组,并打印出分组名称和对应的数据。

8. 分组聚合的高级用法

8.1 多个聚合函数

我们可以同时应用多个聚合函数:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

result = df.groupby('city')['salary'].agg(['mean', 'min', 'max', 'count'])

print(result)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子计算了每个城市的平均薪资、最低薪资、最高薪资和员工数量。

8.2 不同列应用不同的聚合函数

我们可以为不同的列指定不同的聚合函数:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000],
    'age': [25, 30, 35, 28, 32]
})

result = df.groupby('city').agg({
    'salary': ['mean', 'max'],
    'age': ['min', 'max']
})

print(result)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子对薪资计算了平均值和最大值,对年龄计算了最小值和最大值。

9. 处理缺失值

在进行分组操作时,我们可能会遇到缺失值。Pandas提供了多种处理缺失值的方法:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', np.nan, 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

# 忽略缺失值
result1 = df.groupby('city', dropna=True)['salary'].mean()

# 将缺失值视为一个分组
result2 = df.groupby('city', dropna=False)['salary'].mean()

print("Ignoring NaN:")
print(result1)
print("\nIncluding NaN as a group:")
print(result2)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子展示了如何在分组时处理缺失值,可以选择忽略缺失值或将其视为一个单独的分组。

10. 分组后的排序

有时我们可能想要根据聚合结果对分组进行排序:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

result = df.groupby('city')['salary'].mean().sort_values(ascending=False)

print(result)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子按城市分组计算平均薪资,然后按平均薪资降序排列。

11. 分组和时间序列数据

GroupBy操作在处理时间序列数据时也非常有用:

import pandas as pd
import numpy as np

# 创建一个包含日期的DataFrame
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
df = pd.DataFrame({
    'date': dates,
    'sales': np.random.randint(100, 1000, size=len(dates))
})

# 按月分组并计算每月的总销售额
monthly_sales = df.groupby(df['date'].dt.to_period('M'))['sales'].sum()

print(monthly_sales)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子创建了一个包含全年每日销售数据的DataFrame,然后按月分组并计算每月的总销售额。

12. 分组和窗口函数

Pandas的GroupBy操作可以与窗口函数结合使用,实现更复杂的分析:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

# 计算每个城市内的累计薪资和
df['cumulative_salary'] = df.groupby('city')['salary'].cumsum()

print(df)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子计算了每个城市内的累计薪资和。

13. 分组和数据透视表

GroupBy操作与数据透视表(pivot table)密切相关:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'date': pd.date_range(start='2023-01-01', periods=100),
    'city': np.random.choice(['New York', 'London', 'Paris'], 100),
    'product': np.random.choice(['A', 'B', 'C'], 100),
    'sales': np.random.randint(10, 100, 100)
})

pivot_table = pd.pivot_table(df, values='sales', index='city', columns='product', aggfunc='sum')

print(pivot_table)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子创建了一个数据透视表,显示每个城市每种产品的总销售额。

14. 分组和重采样

对于时间序列数据,我们可以结合使用GroupBy和重采样:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'date': pd.date_range(start='2023-01-01', periods=1000, freq='H'),
    'city': np.random.choice(['New York', 'London', 'Paris'], 1000),
    'temperature': np.random.normal(20, 5, 1000)
})

# 按城市分组,然后对每个城市的数据进行日重采样
daily_avg_temp = df.groupby('city').resample('D', on='date')['temperature'].mean()

print(daily_avg_temp)

这个例子按城市分组,然后对每个城市的温度数据进行日重采样,计算每日平均温度。

15. 分组和滚动计算

我们可以在分组内进行滚动计算:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'date': pd.date_range(start='2023-01-01', periods=100),
    'city': np.random.choice(['New York', 'London', 'Paris'], 100),
    'sales': np.random.randint(100, 1000, 100)
})

# 按城市分组,然后计算7天滚动平均销售额
rolling_avg = df.groupby('city').rolling(window=7, on='date')['sales'].mean()

print(rolling_avg)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子按城市分组,然后计算每个城市的7天滚动平均销售额。

结论

Pandas的GroupBy操作是一个强大而灵活的工具,可以帮助我们高效地分析和处理数据。通过本文的详细介绍和丰富的示例,我们深入探讨了Pandas中GroupBy操作的各个方面,从基本概念到高级应用。以下是一些关键点的总结:

  1. GroupBy的基本用法允许我们按一个或多个列对数据进行分组。
  2. 我们可以使用groups属性和get_group()方法来获取分组信息。
  3. GroupBy支持多种聚合操作,如sum()、mean()、count()等。
  4. 可以对分组应用自定义函数,使用apply()或transform()方法。
  5. 分组操作可以与其他Pandas功能结合,如时间序列分析、窗口函数和数据透视表。
  6. 在处理大型数据集时,GroupBy操作可能会遇到性能问题,此时可以考虑使用其他优化方法。

16. 分组和连接操作

GroupBy操作也可以与DataFrame的连接操作结合使用:

import pandas as pd

# 创建两个DataFrame
df1 = pd.DataFrame({
    'city': ['New York', 'London', 'Paris', 'Tokyo'],
    'population': [8400000, 8900000, 2100000, 13900000]
})

df2 = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London', 'Tokyo'],
    'salary': [50000, 60000, 70000, 55000, 65000, 75000]
})

# 按城市分组计算平均薪资
avg_salary = df2.groupby('city')['salary'].mean().reset_index()

# 将平均薪资信息与人口信息连接
result = pd.merge(df1, avg_salary, on='city')

print(result)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子首先计算了每个城市的平均薪资,然后将结果与城市人口信息连接起来。

17. 分组和过滤

我们可以基于分组的结果对数据进行过滤:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London', 'Tokyo'],
    'salary': [50000, 60000, 70000, 55000, 65000, 75000]
})

# 过滤出平均薪资超过60000的城市
high_salary_cities = df.groupby('city').filter(lambda x: x['salary'].mean() > 60000)

print(high_salary_cities)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子过滤出了平均薪资超过60000的城市的所有数据。

18. 分组和数据规范化

GroupBy操作可以用于数据的规范化处理:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London', 'Tokyo'],
    'salary': [50000, 60000, 70000, 55000, 65000, 75000]
})

# 计算每个城市内的薪资占比
df['salary_ratio'] = df.groupby('city')['salary'].transform(lambda x: x / x.sum())

print(df)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子计算了每个人的薪资在其所在城市总薪资中的占比。

19. 处理多级索引

GroupBy操作会产生多级索引,我们可以使用unstack()方法来重塑数据:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London', 'Tokyo'],
    'department': ['IT', 'HR', 'Finance', 'IT', 'HR', 'Finance'],
    'salary': [50000, 60000, 70000, 55000, 65000, 75000]
})

# 按城市和部门分组计算平均薪资
result = df.groupby(['city', 'department'])['salary'].mean().unstack()

print(result)

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子按城市和部门分组计算平均薪资,然后使用unstack()方法将结果转换为更易读的表格形式。

20. 分组和可视化

最后,我们可以将GroupBy操作的结果用于数据可视化:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London', 'Tokyo'],
    'salary': [50000, 60000, 70000, 55000, 65000, 75000]
})

# 计算每个城市的平均薪资
avg_salary = df.groupby('city')['salary'].mean()

# 绘制条形图
avg_salary.plot(kind='bar')
plt.title('Average Salary by City')
plt.xlabel('City')
plt.ylabel('Average Salary')
plt.show()

Output:

Pandas GroupBy 分组操作及获取分组详解

这个例子计算了每个城市的平均薪资,并使用matplotlib库绘制了一个条形图来可视化结果。

通过这些丰富的示例,我们可以看到Pandas的GroupBy操作在数据分析中的强大功能和灵活性。它不仅可以进行基本的分组和聚合,还可以与Pandas的其他功能无缝集成,实现复杂的数据处理和分析任务。

在实际的数据分析项目中,熟练运用GroupBy操作可以大大提高我们处理和分析数据的效率。无论是处理金融数据、用户行为数据,还是科研数据,GroupBy都是一个不可或缺的工具。

然而,需要注意的是,在处理大型数据集时,GroupBy操作可能会占用大量内存和计算资源。在这种情况下,我们可能需要考虑使用其他技术,如数据库的聚合函数或分布式计算框架(如Apache Spark)来处理数据。

总的来说,Pandas的GroupBy操作是一个强大而灵活的工具,掌握它可以让我们更有效地进行数据分析和处理。通过不断实践和探索,我们可以发现更多GroupBy操作的应用场景,从而在数据分析工作中游刃有余。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程