最强总结! 十大Pandas分组和分区操作 !!

文摘   2024-10-04 11:26   山西  

哈喽,我是小白~

今儿和大家聊聊Pandas的分组和分区的一些操作!~

在机器学习实验中,Pandas的分组和分区操作可以高效地对数据进行汇总、分割和分析,从而揭示数据的分布规律与特征差异。通过分组汇总操作,如groupby()pivot_table(),可以对不同类别或维度的数据进行精细的聚合分析,帮助挖掘隐藏的模式。分箱操作如cut()qcut()则能够将连续型特征离散化,便于进一步特征工程和模型训练。

今天涉及到的十种Pandas的分组和分区操作有:

  • groupby()
  • agg()
  • transform()
  • apply()
  • filter()
  • pivot_table()
  • cut()
  • qcut()
  • rolling()
  • expanding()

历史 Pandas 精华

Pandas 十大清洗技巧

Pandas 十大转化技巧

Pandas 十大聚合技巧

十大 Pandas时间序列处理方法

十大Pandas缺失值处理技巧

十大pandas合并与连接操作

1. groupby()

groupby() 是 Pandas 中最重要的操作之一,用于根据一个或多个列的值对数据进行分组。分组后,你可以对每个分组的数据进行聚合(如求平均、求和等)、转换或过滤。通常,groupby() 与聚合函数结合使用,如 mean()sum()count() 等。

操作步骤

groupby() 操作通常可以分为三个步骤:

  1. 分组:根据一个或多个列对数据进行分组。
  2. 应用(apply):在每个分组上应用某种函数或操作,如求平均值或总和。
  3. 合并(combine):将操作的结果合并为一个新的 DataFrame

使用场景

  • 分析某类数据在不同类别下的变化趋势。
  • 在机器学习中,常用于对类别特征(categorical features)的特征工程。
  • 数据聚合(汇总统计)场景,例如计算各个类别的销售总额、平均值、最小值等。

代码实现

import pandas as pd

# 示例数据
data = {
    'Category': ['A''B''A''B''C''A''C''B'],
    'Value': [1020304050607080],
    'Count': [12345678]
}
df = pd.DataFrame(data)

# 按 'Category' 列进行分组,计算每个分组的 'Value' 列的平均值
grouped_mean = df.groupby('Category')['Value'].mean()
print("各类别的平均值:\n", grouped_mean)

# 按 'Category' 列进行分组,计算每个分组的 'Value' 和 'Count' 列的总和
grouped_sum = df.groupby('Category').sum()
print("\n各类别的总和:\n", grouped_sum)

# 按 'Category' 分组,并统计每个分组的大小
grouped_size = df.groupby('Category').size()
print("\n各类别的大小:\n", grouped_size)

输出

各类别的平均值:
Category
A    33.333333
B    46.666667
C    60.000000
Name: Value, dtype: float64

各类别的总和:
          Value  Count
Category              
A            100      10
B            140      14
C            120      12

各类别的大小:
Category
A    3
B    3
C    2
dtype: int64

关键点

  • groupby() 返回的是一个分组对象,必须通过聚合或转换函数才能得到结果。
  • 可以根据单列或多列进行分组。
  • 支持多种聚合函数,如 mean()sum()count() 等。
  • 分组后的操作返回的是一个新的 DataFrame 或 Series,具体取决于操作的列数和结果类型。

2. agg()

agg() 用于对 groupby() 的结果进行多重聚合操作。通过 agg(),你可以在不同列上应用不同的聚合函数,甚至在同一列上应用多个聚合函数。

操作步骤

  1. 选择分组对象:通过 groupby() 创建分组对象。
  2. 应用 agg() 聚合函数:在不同列上指定不同的聚合操作,或者对同一列应用多个函数。
  3. 返回聚合结果:最终结果是一个 DataFrame,每一列显示不同聚合操作的结果。

使用场景

  • 在一个数据框中,对不同列进行不同的聚合操作。例如,计算某列的平均值,同时计算另一列的总和。
  • 同时对同一列执行多个操作,如计算平均值、标准差、最大值等。

代码实现

# 按 'Category' 列分组,并对 'Value' 列进行多个聚合操作
grouped_agg = df.groupby('Category').agg({
    'Value': ['mean''sum''max'],
    'Count': ['min''count']
})
print(grouped_agg)

输出

          Value                Count     
           mean  sum max min count
Category                           
A        33.3333  100  60   1     3
B        46.6667  140  80   2     3
C        60.0000  120  70   5     2

关键点

  • agg() 支持在不同列上应用不同的聚合函数,也支持在同一列上应用多个聚合函数。
  • 返回的结果是一个多级索引的 DataFrame,每一列是对应的聚合操作。

3. transform()

transform() 函数用于将聚合操作的结果“广播”回原始数据框的每一行,而不是直接返回一个汇总后的数据框。transform() 对每个分组执行操作,并返回与输入数据相同大小的结果。

操作步骤

  1. 分组:通过 groupby() 创建分组对象。
  2. 应用 `transform():对每个分组应用函数,并将结果赋值给原始数据中的每一行。
  3. 返回原始大小的 DataFrame 或 `Series。

使用场景

  • 在机器学习中,常用于对特征进行标准化或归一化,保持分组间的一致性。

  • 计算每个分组的统计量并将其分配回原始数据框。

代码实现

# 计算每个分组的平均值,并将其广播回原始数据框
df['Mean_Value'] = df.groupby('Category')['Value'].transform('mean')
print(df)

输出

  Category  Value  Count  Mean_Value
0        A     10      1    33.333333
1        B     20      2    46.666667
2        A     30      3    33.333333
3        B     40      4    46.666667
4        C     50      5    60.000000
5        A     60      6    33.333333
6        C     70      7    60.000000
7        B     80      8    46.666667

关键点

  • transform() 与 agg() 不同,它返回的结果与原始数据框大小相同。
  • 常用于需要保留原始数据框结构的场景,如特征转换、标准化等。

4. apply()

apply() 是一种灵活的函数,它允许你在分组数据上应用自定义函数。apply() 可以返回标量、Series或 DataFrame

操作步骤

  1. 分组:通过 groupby() 创建分组对象。
  2. 应用 `apply():对每个分组应用自定义函数。
  3. 返回结果:根据自定义函数的返回值,结果可以是标量、Series 或 DataFrame

使用场景

  • 对分组数据进行自定义的复杂计算。
  • 当内置的聚合函数不满足需求时,可以使用 apply() 实现更灵活的操作。

代码实现

# 自定义函数:计算每个分组的最大值减去最小值
def range_func(x):
    return x.max() - x.min()

# 按 'Category' 列分组,对 'Value' 列应用自定义函数
grouped_apply = df.groupby('Category')['Value'].apply(range_func)
print(grouped_apply)

输出

Category
A    50
B    60
C    20
Name: Value, dtype: int64

关键点

  • apply() 非常灵活,适用于不能通过内置函数完成的操作。
  • 返回值可以是

标量、Series 或 DataFrame,具体取决于自定义函数的设计。

继续深入介绍 Pandas 中常用的分组和分区操作,下面是余下的六种操作,它们在数据处理和特征工程中非常实用。

5. filter()

filter() 用于根据某些条件对分组后的数据进行过滤,它可以保留符合条件的整个分组。常用于基于某些聚合结果的过滤操作。

操作步骤

  1. 分组:首先使用 groupby() 按某列或多列对数据进行分组。
  2. 应用过滤条件:通过 filter() 函数过滤分组。过滤条件通常是针对每个分组的某些属性(如分组大小、分组中的某个统计量等)。
  3. 返回结果:返回符合条件的分组。

使用场景

  • 根据某些条件(如分组的总和大于某个值)筛选分组。
  • 保留符合业务规则的分组。

代码实现

# 示例数据
data = {'Category': ['A''B''A''B''C''A''C''B'],
        'Value': [1020304050607080]}
df = pd.DataFrame(data)

# 按 'Category' 列分组,保留 'Value' 列总和大于100的分组
filtered_df = df.groupby('Category').filter(lambda x: x['Value'].sum() > 100)
print(filtered_df)

输出

  Category  Value
1        B     20
3        B     40
7        B     80
5        A     60

关键点

  • filter() 保留或删除整个分组,而不是单独的行。
  • 使用 lambda 函数,可以灵活地设置过滤条件。

6. pivot_table()

pivot_table() 类似于 Excel 中的透视表,用于基于某些键(key)对数据进行聚合。它能够灵活地对多维数据进行聚合操作,并返回一个类似于透视表的结构化结果。

操作步骤

  1. 选择索引和列:指定行、列以及要聚合的数值列。
  2. 选择聚合函数:可以使用 mean()sum() 等聚合函数。
  3. 生成透视表:返回一个包含聚合结果的 DataFrame

使用场景

  • 当你需要以透视表的方式查看数据时,pivot_table() 非常有用。
  • 适用于多维数据聚合。

代码实现

# 示例数据
data = {
    'Category': ['A''B''A''B''C''A''C''B'],
    'SubCategory': ['X''X''Y''Y''X''Y''X''X'],
    'Value': [1020304050607080]
}
df = pd.DataFrame(data)

# 创建透视表,按 'Category' 和 'SubCategory' 分组,并对 'Value' 进行聚合
pivot_df = df.pivot_table(values='Value', index='Category', columns='SubCategory', aggfunc='sum')
print(pivot_df)

输出

SubCategory     X     Y
Category               
A            10.0  90.0
B           100.0  40.0
C           120.0   NaN

关键点

  • pivot_table() 是一种强大的数据透视工具,可以轻松处理多维数据。
  • 默认使用 mean() 作为聚合函数,但可以通过 aggfunc 参数指定其他聚合函数。

7. cut()

cut() 用于将连续的数值数据分箱(binning),将数据划分为不同的区间(bins),并将每个数据点分配到对应的区间。这是特征工程中常用的操作,尤其是在处理连续型特征时。

操作步骤

  1. 定义区间:通过 cut() 函数将数值数据划分为固定区间。
  2. 分配数据到区间:根据区间将数据进行分配。
  3. 返回结果:返回分配后的分箱标签。

使用场景

  • 处理连续型特征,将其离散化为不同的区间。
  • 在分类模型中,将连续变量转化为类别型特征。

代码实现

# 示例数据
values = [22252735455565758595]

# 使用 cut() 将值划分为 4 个区间
bins = pd.cut(values, bins=4)
print(bins)

输出

[(21.927, 40.0], (21.927, 40.0], (21.927, 40.0], (21.927, 40.0], (40.0, 58.0], (40.0, 58.0], (58.0, 75.0], (58.0, 75.0], (75.0, 93.0], (75.0, 93.0]]
Categories (4, interval[float64, right]): [(21.927, 40.0] < (40.0, 58.0] < (58.0, 75.0] < (75.0, 93.0]]

关键点

  • cut() 常用于对连续数据进行分箱操作。
  • 可以手动定义区间,也可以自动生成等宽或等频区间。

8. qcut()

qcut() 是 cut() 的变体,区别在于 cut() 按照等宽区间分箱,而 qcut() 按照等频分箱(每个区间包含相同数量的数据点)。这是处理数据偏态分布时的一种有效方法。

操作步骤

  1. 定义分位数:通过 qcut() 根据指定的分位数将数据划分为等频区间。
  2. 分配数据到区间:根据分位数将数据分配到区间。
  3. 返回结果:返回分配后的分箱标签。

使用场景

  • 在数据呈现不均匀分布时,将数据分为等频区间是一个不错的选择。

代码实现

# 使用 qcut() 将数据按分位数划分为 4 个等频区间
q_bins = pd.qcut(values, q=4)
print(q_bins)

输出

[(21.999, 35.0], (21.999, 35.0], (21.999, 35.0], (21.999, 35.0], (35.0, 55.0], (55.0, 65.0], (65.0, 75.0], (75.0, 85.0], (85.0, 95.0], (85.0, 95.0]]
Categories (4, interval[float64, right]): [(21.999, 35.0] < (35.0, 55.0] < (55.0, 65.0] < (65.0, 95.0]]

关键点

  • qcut() 按等频区间对数据进行分箱,非常适合处理有偏分布的数据。
  • 常用于特征工程中,将连续变量转换为离散类别型变量。

9. rolling()

rolling() 用于计算移动窗口(rolling window)上的统计量。移动窗口是一种在时间序列或连续数据上进行聚合计算的工具,它可以对滑动窗口内的数据进行操作,如求平均、求和等。

操作步骤

  1. 定义窗口大小:通过 rolling() 指定窗口大小。
  2. 应用聚合函数:在滚动窗口上应用如 mean()sum() 等聚合函数。
  3. 返回结果:返回一个与原始数据大小相同的 Series 或 DataFrame

使用场景


常用于时间序列分析,计算移动平均、移动总和等。

  • 数据平滑处理。

代码实现

# 示例数据
ts = pd.Series([12345678910])

# 计算滚动窗口为 3 的移动平均
rolling_mean = ts.rolling(window=3).mean()
print(rolling_mean)

输出

0     NaN
1     NaN
2     2.0
3     3.0
4     4.0
5     5.0
6     6.0
7     7.0
8     8.0
9     9.0
dtype: float64

关键点

  • rolling() 可以指定窗口大小和步长。
  • 常用于时间序列和信号处理领域,计算平滑的时间序列数据。

10. expanding()

expanding() 是累积窗口的版本,与 rolling() 类似,但它计算的是从开始到当前行的所有数据的聚合。它用于累计和递增计算,如累计总和、累计均值等。

操作步骤

  1. 定义窗口:通过 expanding() 创建累积窗口。
  2. 应用聚合函数:在累积窗口上应用聚合操作,如 sum()mean() 等。
  3. 返回结果:返回一个与原始数据大小相同的 Series 或 DataFrame

使用场景

  • 累计总和、累计平均等递增计算场景。
  • 常用于分析序列数据中的累积趋势。

代码实现

# 计算累积平均
expanding_mean = ts.expanding().mean()
print(expanding_mean)

输出

0     1.0
1     1.5
2     2.0
3     2.5
4     3.0
5     3.5
6     4.0
7     4.5
8     5.0
9     5.5
dtype: float64

关键点

  • expanding() 用于从序列的开始到当前点的累计计算。
  • 适用于需要观察累积效果的数据分析任务。

完整案例

该案例会模拟一个虚拟的销售数据集,包括日期、产品类别、地区、销售额和折扣等信息。

数据分析任务

  1. 使用 groupby() 对销售额按产品类别和地区进行分组汇总。
  2. 使用 pivot_table() 创建不同产品类别和地区的销售额透视表。
  3. 使用 rolling() 计算各类别产品的销售额的移动平均值,探索其时间趋势。
  4. 使用 cut() 和 qcut() 分析销售额的分布情况。
  5. 结合上述操作,绘制多个可视化图表。

案例代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 设置随机种子,确保结果可复现
np.random.seed(42)

# 生成虚拟数据集
n = 500
dates = pd.date_range('2023-01-01', periods=n, freq='D')
categories = np.random.choice(['Electronics''Clothing''Furniture'], size=n)
regions = np.random.choice(['North''South''East''West'], size=n)
sales = np.random.randint(1001000, size=n)
discounts = np.random.uniform(00.3, size=n)

# 构造DataFrame
df = pd.DataFrame({
    'Date': dates,
    'Category': categories,
    'Region': regions,
    'Sales': sales,
    'Discount': discounts
})

# 1. 按产品类别和地区分组,计算总销售额
grouped_sales = df.groupby(['Category''Region'])['Sales'].sum().reset_index()

# 2. 使用 pivot_table 生成透视表
pivot_table = df.pivot_table(values='Sales', index='Category', columns='Region', aggfunc='sum')

# 3. 计算移动平均销售额,使用滚动窗口
df['Rolling_Sales'] = df.groupby('Category')['Sales'].transform(lambda x: x.rolling(window=7).mean())

# 4. 将销售额分为4个区间,使用 cut 和 qcut
df['Sales_Bins'] = pd.cut(df['Sales'], bins=4, labels=['Low''Medium''High''Very High'])
df['Sales_Quartiles'] = pd.qcut(df['Sales'], q=4, labels=['Q1''Q2''Q3''Q4'])

# 绘制图形
fig, axes = plt.subplots(22, figsize=(1410))

# 图1: 各类别产品在不同地区的总销售额柱状图
sns.barplot(x='Category', y='Sales', hue='Region', data=grouped_sales, ax=axes[00])
axes[00].set_title('Total Sales by Category and Region')
axes[00].set_xlabel('Category')
axes[00].set_ylabel('Total Sales')

# 图2: 移动平均销售额的时间趋势
for category in df['Category'].unique():
    sns.lineplot(x='Date', y='Rolling_Sales', data=df[df['Category'] == category], label=category, ax=axes[01])
axes[01].set_title('Rolling Mean of Sales Over Time by Category')
axes[01].set_xlabel('Date')
axes[01].set_ylabel('Rolling Mean Sales')

# 图3: 使用 cut 的销售额分箱结果的分布
sns.countplot(x='Sales_Bins', data=df, palette='viridis', ax=axes[10])
axes[10].set_title('Sales Distribution by Bins (Using cut)')
axes[10].set_xlabel('Sales Bins')
axes[10].set_ylabel('Count')

# 图4: 使用 qcut 的销售额四分位分布
sns.countplot(x='Sales_Quartiles', data=df, palette='coolwarm', ax=axes[11])
axes[11].set_title('Sales Distribution by Quartiles (Using qcut)')
axes[11].set_xlabel('Sales Quartiles')
axes[11].set_ylabel('Count')

# 调整图形布局
plt.tight_layout()
plt.show()
  1. 数据集生成:生成了一个包含 500 条数据的虚拟销售数据集。数据集包含 日期产品类别地区销售额 和 折扣 五个字段。

  2. 分组汇总操作:使用 groupby() 按 Category 和 Region 分组,汇总计算 Sales 销售额。

  3. 透视表操作:使用 pivot_table() 生成透视表,展示不同 Category 在各个 Region 的总销售额。

  4. 移动平均计算:使用 rolling() 对 Sales 列进行移动平均计算,以探讨不同产品类别在时间序列上的销售趋势。

  5. 分箱操作:使用 cut() 和 qcut() 对 Sales 列进行分箱,分别生成等宽和等频的销售额分布。

  • 图1:展示不同产品类别在各个地区的总销售额分布情况,可以观察到不同地区对不同产品的偏好。
  • 图2:展示了不同类别产品的移动平均销售趋势,可以观察各个类别的销售波动情况。
  • 图3:通过 cut() 分箱,展示销售额的区间分布情况,了解销售额的具体分布。
  • 图4:通过 qcut() 将销售额按四分位数划分,观察销售额在不同区间的分布情况。

历史 Pandas 精华

Pandas 十大清洗技巧

Pandas 十大转化技巧

Pandas 十大聚合技巧

十大 Pandas时间序列处理方法

十大Pandas缺失值处理技巧

十大pandas合并与连接操作

最后

以上就是今天所有的内容了。
如果对你来说比较有用,记得点赞、收藏,慢慢学习~
下期会有更多干货等着你!~


Python和机器学习初学者
Python和机器学习分享,只写干货,一起学习~
 最新文章