Pandas GroupBy 创建新列:高效数据分组与列操作指南

Pandas GroupBy 创建新列:高效数据分组与列操作指南

参考:pandas groupby create new column

在数据分析和处理中,Pandas 的 GroupBy 操作是一个强大的工具,它允许我们根据一个或多个列对数据进行分组,并在分组的基础上进行各种计算和操作。本文将详细介绍如何使用 Pandas GroupBy 创建新列,这是一个常见且有用的数据处理技巧。我们将探讨不同的场景和方法,以帮助您更好地理解和应用这一功能。

1. GroupBy 基础概念

在深入探讨如何使用 GroupBy 创建新列之前,我们先来回顾一下 GroupBy 的基本概念。

GroupBy 操作的核心思想是将数据按照一个或多个列的值进行分组,然后在每个分组上应用特定的操作。这种操作可以是聚合(如求和、平均值)、转换或过滤等。

以下是一个简单的 GroupBy 示例:

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'sales': [100, 200, 300, 150, 250]
}
df = pd.DataFrame(data)

# 按 name 分组并计算销售总额
grouped = df.groupby('name')['sales'].sum()

print("pandasdataframe.com - GroupBy 基础示例:")
print(grouped)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

在这个例子中,我们按 ‘name’ 列对数据进行分组,然后计算每个人的销售总额。这展示了 GroupBy 的基本用法。

2. 使用 GroupBy 创建新列的基本方法

现在,让我们探讨如何使用 GroupBy 创建新列。最常见的方法是使用 transform() 函数。这个函数允许我们对分组后的数据应用操作,并返回与原始 DataFrame 相同长度的结果。

2.1 使用 transform() 创建新列

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'sales': [100, 200, 300, 150, 250]
}
df = pd.DataFrame(data)

# 使用 transform() 创建新列
df['avg_sales'] = df.groupby('name')['sales'].transform('mean')

print("pandasdataframe.com - 使用 transform() 创建新列:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

在这个例子中,我们创建了一个新列 ‘avg_sales’,它包含每个人的平均销售额。transform('mean') 计算每个分组的平均值,并将结果广播到原始 DataFrame 的每一行。

2.2 使用自定义函数与 transform()

我们还可以使用自定义函数与 transform() 结合,以实现更复杂的操作:

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'sales': [100, 200, 300, 150, 250]
}
df = pd.DataFrame(data)

# 自定义函数计算销售额与平均值的差
def sales_diff(x):
    return x - x.mean()

# 使用自定义函数创建新列
df['sales_diff'] = df.groupby('name')['sales'].transform(sales_diff)

print("pandasdataframe.com - 使用自定义函数与 transform() 创建新列:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何使用自定义函数计算每个人的销售额与其平均销售额的差异。

3. 高级 GroupBy 创建新列技巧

除了基本方法,还有一些高级技巧可以帮助我们更灵活地使用 GroupBy 创建新列。

3.1 使用多列进行分组

有时我们需要根据多个列进行分组,然后创建新列:

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'category': ['A', 'B', 'A', 'B', 'A'],
    'sales': [100, 200, 300, 150, 250]
}
df = pd.DataFrame(data)

# 使用多列分组并创建新列
df['group_avg'] = df.groupby(['name', 'category'])['sales'].transform('mean')

print("pandasdataframe.com - 使用多列分组创建新列:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何根据 ‘name’ 和 ‘category’ 两列进行分组,然后计算每个组的平均销售额。

3.2 使用 agg() 创建多个新列

agg() 函数允许我们同时应用多个聚合函数,并创建多个新列:

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'sales': [100, 200, 300, 150, 250]
}
df = pd.DataFrame(data)

# 使用 agg() 创建多个新列
agg_results = df.groupby('name')['sales'].agg(['mean', 'sum', 'count'])
df = df.merge(agg_results, left_on='name', right_index=True, suffixes=('', '_agg'))

print("pandasdataframe.com - 使用 agg() 创建多个新列:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何使用 agg() 函数同时计算平均值、总和和计数,然后将结果合并回原始 DataFrame。

3.3 使用 apply() 进行复杂操作

对于更复杂的操作,我们可以使用 apply() 函数:

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
    'city': ['New York', 'London', 'Paris', 'New York', 'London'],
    'sales': [100, 200, 300, 150, 250]
}
df = pd.DataFrame(data)

# 使用 apply() 进行复杂操作
def complex_calc(group):
    return pd.Series({
        'total_sales': group['sales'].sum(),
        'avg_sales': group['sales'].mean(),
        'sales_range': group['sales'].max() - group['sales'].min()
    })

results = df.groupby('name').apply(complex_calc)
df = df.merge(results, left_on='name', right_index=True, suffixes=('', '_calc'))

print("pandasdataframe.com - 使用 apply() 进行复杂操作:")
print(df)

这个例子展示了如何使用 apply() 函数执行更复杂的计算,包括计算总销售额、平均销售额和销售范围。

4. 处理时间序列数据

在处理时间序列数据时,GroupBy 创建新列也非常有用。

4.1 按时间间隔分组

import pandas as pd
import numpy as np

# 创建示例时间序列数据
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
data = {
    'date': dates,
    'sales': np.random.randint(100, 1000, size=len(dates))
}
df = pd.DataFrame(data)

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

print("pandasdataframe.com - 按时间间隔分组:")
print(df.head())

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何按月对销售数据进行分组,并计算每个月的总销售额。

4.2 计算滚动平均

import pandas as pd
import numpy as np

# 创建示例时间序列数据
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
data = {
    'date': dates,
    'sales': np.random.randint(100, 1000, size=len(dates))
}
df = pd.DataFrame(data)

# 计算7天滚动平均
df['rolling_avg'] = df.groupby(df['date'].dt.to_period('M'))['sales'].transform(lambda x: x.rolling(window=7).mean())

print("pandasdataframe.com - 计算滚动平均:")
print(df.head(10))

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个月内的7天滚动平均销售额。

5. 处理分类数据

对于分类数据,GroupBy 创建新列也有一些特殊的应用。

5.1 计算每个类别的占比

import pandas as pd

# 创建示例分类数据
data = {
    'category': ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B'],
    'value': [10, 20, 30, 15, 25, 35, 12, 22]
}
df = pd.DataFrame(data)

# 计算每个类别的占比
total = df['value'].sum()
df['category_percentage'] = df.groupby('category')['value'].transform(lambda x: x.sum() / total * 100)

print("pandasdataframe.com - 计算每个类别的占比:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个类别在总体中的百分比。

5.2 计算类别内的排名

import pandas as pd

# 创建示例分类数据
data = {
    'category': ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B'],
    'value': [10, 20, 30, 15, 25, 35, 12, 22]
}
df = pd.DataFrame(data)

# 计算类别内的排名
df['rank_within_category'] = df.groupby('category')['value'].transform(lambda x: x.rank(method='dense', ascending=False))

print("pandasdataframe.com - 计算类别内的排名:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个值在其类别内的排名。

6. 处理缺失值

在使用 GroupBy 创建新列时,处理缺失值是一个常见的问题。

6.1 填充缺失值

import pandas as pd
import numpy as np

# 创建包含缺失值的示例数据
data = {
    'group': ['A', 'A', 'B', 'B', 'C', 'C'],
    'value': [10, np.nan, 20, 25, np.nan, 30]
}
df = pd.DataFrame(data)

# 使用组内平均值填充缺失值
df['filled_value'] = df.groupby('group')['value'].transform(lambda x: x.fillna(x.mean()))

print("pandasdataframe.com - 填充缺失值:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何使用每个组的平均值来填充缺失值。

6.2 计算非缺失值的比例

import pandas as pd
import numpy as np

# 创建包含缺失值的示例数据
data = {
    'group': ['A', 'A', 'B', 'B', 'C', 'C'],
    'value': [10, np.nan, 20, 25, np.nan, 30]
}
df = pd.DataFrame(data)

# 计算每个组中非缺失值的比例
df['non_null_ratio'] = df.groupby('group')['value'].transform(lambda x: x.notnull().mean())

print("pandasdataframe.com - 计算非缺失值的比例:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个组中非缺失值的比例。

7. 高级应用:窗口函数

Pandas 的 GroupBy 操作还可以用来实现类似 SQL 窗口函数的功能。

7.1 计算累积和

import pandas as pd

# 创建示例数据
data = {
    'date': pd.date_range(start='2023-01-01', periods=10),
    'sales': [100, 150, 200, 120, 180, 210, 160, 230, 190, 250]
}
df = pd.DataFrame(data)

# 计算累积和
df['cumulative_sales'] = df.groupby(df['date'].dt.to_period('M'))['sales'].transform(lambda x: x.cumsum())

print("pandasdataframe.com - 计算累积和:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个月内的累积销售额。

7.2 计算移动平均

import pandas as pd

# 创建示例数据
data = {
    'date': pd.date_range(start='2023-01-01', periods=10),
    'sales': [100, 150, 200, 120, 180, 210, 160, 230, 190, 250]
}
df = pd.DataFrame(data)

# 计算3天移动平均df['moving_average'] = df.groupby(df['date'].dt.to_period('M'))['sales'].transform(lambda x: x.rolling(window=3).mean())

print("pandasdataframe.com - 计算移动平均:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个月内的3天移动平均销售额。

8. 性能优化技巧

在处理大型数据集时,GroupBy 操作可能会变得很慢。以下是一些优化性能的技巧:

8.1 使用 numba 加速

对于计算密集型的操作,可以使用 numba 来加速:

import pandas as pd
import numpy as np
from numba import jit

# 创建大型示例数据
n = 1000000
data = {
    'group': np.random.choice(['A', 'B', 'C'], n),
    'value': np.random.rand(n)
}
df = pd.DataFrame(data)

@jit(nopython=True)
def fast_mean(values):
    return values.mean()

# 使用 numba 加速的 GroupBy 操作
df['group_mean'] = df.groupby('group')['value'].transform(fast_mean)

print("pandasdataframe.com - 使用 numba 加速:")
print(df.head())

这个例子展示了如何使用 numba 来加速 GroupBy 操作。

8.2 使用 categoricals

对于具有有限且重复值的列,使用 categoricals 可以提高性能:

import pandas as pd
import numpy as np

# 创建大型示例数据
n = 1000000
data = {
    'group': np.random.choice(['A', 'B', 'C'], n),
    'value': np.random.rand(n)
}
df = pd.DataFrame(data)

# 将 group 列转换为 categorical
df['group'] = df['group'].astype('category')

# 执行 GroupBy 操作
df['group_mean'] = df.groupby('group')['value'].transform('mean')

print("pandasdataframe.com - 使用 categoricals:")
print(df.head())

这个例子展示了如何将分组列转换为 categorical 类型以提高性能。

9. 处理多层索引

有时,我们需要处理多层索引的 DataFrame。GroupBy 操作在这种情况下也非常有用。

9.1 创建多层索引

import pandas as pd
import numpy as np

# 创建多层索引的示例数据
index = pd.MultiIndex.from_product([['A', 'B'], ['X', 'Y', 'Z']], names=['group', 'subgroup'])
data = pd.DataFrame({'value': np.random.rand(6)}, index=index)

# 在多层索引上执行 GroupBy 操作
data['group_mean'] = data.groupby(level='group')['value'].transform('mean')

print("pandasdataframe.com - 多层索引 GroupBy:")
print(data)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何在多层索引的 DataFrame 上执行 GroupBy 操作。

9.2 在多层索引上创建新列

import pandas as pd
import numpy as np

# 创建多层索引的示例数据
index = pd.MultiIndex.from_product([['A', 'B'], ['X', 'Y', 'Z']], names=['group', 'subgroup'])
data = pd.DataFrame({'value': np.random.rand(6)}, index=index)

# 在多层索引上创建新列
data['subgroup_diff'] = data.groupby(level='subgroup')['value'].transform(lambda x: x - x.mean())

print("pandasdataframe.com - 在多层索引上创建新列:")
print(data)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何在多层索引的 DataFrame 上创建基于子组的新列。

10. 处理字符串数据

GroupBy 操作也可以用于处理字符串数据。

10.1 字符串连接

import pandas as pd

# 创建示例数据
data = {
    'group': ['A', 'A', 'B', 'B', 'C'],
    'item': ['apple', 'banana', 'cherry', 'date', 'elderberry']
}
df = pd.DataFrame(data)

# 使用 GroupBy 连接字符串
df['combined_items'] = df.groupby('group')['item'].transform(lambda x: ', '.join(x))

print("pandasdataframe.com - 字符串连接:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何使用 GroupBy 操作来连接同一组内的字符串。

10.2 计算字符串长度统计

import pandas as pd

# 创建示例数据
data = {
    'group': ['A', 'A', 'B', 'B', 'C'],
    'text': ['hello', 'world', 'pandas', 'dataframe', 'groupby']
}
df = pd.DataFrame(data)

# 计算每组的平均字符串长度
df['avg_length'] = df.groupby('group')['text'].transform(lambda x: x.str.len().mean())

print("pandasdataframe.com - 计算字符串长度统计:")
print(df)

Output:

Pandas GroupBy 创建新列:高效数据分组与列操作指南

这个例子展示了如何计算每个组内字符串的平均长度。

结论

Pandas GroupBy 创建新列是一个强大而灵活的数据处理工具。通过本文介绍的各种方法和技巧,您可以更有效地处理各种类型的数据,包括数值数据、时间序列数据、分类数据和字符串数据。从基本的聚合操作到复杂的窗口函数,GroupBy 操作为数据分析提供了丰富的可能性。

在实际应用中,选择合适的 GroupBy 方法和技巧可以大大提高数据处理的效率和灵活性。同时,注意性能优化和正确处理缺失值也是使用 GroupBy 时需要考虑的重要因素。

随着数据规模和复杂性的增加,掌握这些 GroupBy 技巧将使您能够更好地应对各种数据分析挑战,提高工作效率,并从数据中获得更深入的洞察。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程