如何用Python Pandas提取每个ID的最大/最小采购量及对应日期?
问题描述
数据示例
| ID | purchaseDate(采购日期) | numOfItemsPurchased(采购数量) |
|---|---|---|
| 12 | 12-10-2023 | 2 |
| 12 | 12-01-2023 | 34 |
| 56 | 24-03-2020 | 12 |
| 23 | 23-12-2012 | 1 |
| 23 | 23-05-2012 | 3 |
| 23 | 23-06-2012 | 4 |
| 24 | 12-10-2023 | 24 |
| 38 | 23-02-2012 | 21 |
| 16 | 12-10-2023 | 34 |
| 54 | 02-09-2020 | |
| 54 | 24-03-2020 | 19 |
期望结果
| ID | maxPurchaseDate(最大采购量日期) | maxPurchaseAmount(最大采购量) | leastPurchaseDate(最小采购量日期) | leastPurchaseAmount(最小采购量) |
|---|---|---|---|---|
| 12 | 12-01-2023 | 34 | 12-10-2023 | 2 |
| 56 | 24-03-2020 | 12 | 24-03-2020 | 12 |
| 23 | 23-06-2012 | 4 | 23-12-2012 | 1 |
| 24 | 12-10-2023 | 24 | 12-10-2023 | 24 |
| 38 | 23-02-2012 | 21 | 23-02-2012 | 21 |
| 16 | 12-10-2023 | 34 | 12-10-2023 | 34 |
| 54 | 24-03-2020 | 19 | 02-09-2020 | 11 |
尝试过的代码及问题
- 执行以下代码时出现
KeyError: 'purchaseDate'(已确认列名无拼写错误且执行过fillna(0)):
details = data.groupby('ID').min()['purchaseDate']
- 以下代码无报错,但无法添加更多列:
details = data.groupby('ID').min()['numOfItemsPurchased']
- 执行聚合代码时出现
TypeError: '<=' not supported between instances of 'int' and 'str':
data.groupby(['ID']).agg({'purchaseDate': [np.min,np.max], 'numOfItemsPurchased' : [np.min,np.max]})
解决方案
问题根源
- 第一个报错:
fillna(0)把日期列(字符串类型)填充为整数0,导致groupby.min()自动过滤非数值列,因此找不到purchaseDate。 - 第三个报错:日期列是字符串格式,和填充后的数值混合,引发类型不匹配的比较错误。
步骤1:数据预处理
先针对性处理缺失值,同时把日期转为标准datetime类型:
import pandas as pd import numpy as np # 填充采购数量的缺失值(匹配期望结果用11填充) data['numOfItemsPurchased'] = data['numOfItemsPurchased'].fillna(11) # 转换日期列格式,避免字符串比较问题 data['purchaseDate'] = pd.to_datetime(data['purchaseDate'], format='%d-%m-%Y')
步骤2:提取对应行并合并结果
用idxmax和idxmin定位每个ID下采购量最大/最小的行,直接提取完整数据后合并:
# 获取每个ID采购量最大的行 max_rows = data.loc[data.groupby('ID')['numOfItemsPurchased'].idxmax()] # 获取每个ID采购量最小的行 min_rows = data.loc[data.groupby('ID')['numOfItemsPurchased'].idxmin()] # 合并两行数据,添加后缀区分 result = pd.merge( max_rows[['ID', 'purchaseDate', 'numOfItemsPurchased']], min_rows[['ID', 'purchaseDate', 'numOfItemsPurchased']], on='ID', suffixes=('_max', '_min') ) # 重命名列名匹配期望结果 result.rename(columns={ 'purchaseDate_max': 'maxPurchaseDate(最大采购量日期)', 'numOfItemsPurchased_max': 'maxPurchaseAmount(最大采购量)', 'purchaseDate_min': 'leastPurchaseDate(最小采购量日期)', 'numOfItemsPurchased_min': 'leastPurchaseAmount(最小采购量)' }, inplace=True) # 把日期转回原字符串格式(可选) result['maxPurchaseDate(最大采购量日期)'] = result['maxPurchaseDate(最大采购量日期)'].dt.strftime('%d-%m-%Y') result['leastPurchaseDate(最小采购量日期)'] = result['leastPurchaseDate(最小采购量日期)'].dt.strftime('%d-%m-%Y') print(result)
说明
idxmax/idxmin直接定位目标行索引,能精准关联采购量对应的日期,避免单独聚合日期的逻辑偏差。- 日期转为datetime类型后,后续处理更规范,彻底解决字符串与数值混合的类型错误。
内容的提问来源于stack exchange,提问作者Henry Ibeh
相关产品推荐
相关产品推荐

