Pandas多列GroupBy问题求助:添加Name列后运行异常或超时
Pandas汽车销量分组统计优化方案
问题背景
我是Pandas新手,写了一段分组统计的代码:
for x in data_cp.Owner_Type.unique(): print(data_cp[(data_cp.Owner_Type == x)].groupby(['Owner_Type','Year','Transmission','Fuel_Type','New_Price']) ['Year'].count().sort_values(ascending=False).head(5))
但往分组列里加Name后,程序要么崩溃要么超时,根本没法正常分组。我现在需要完成两个统计需求:
- 按
Year、Owner_Type、Name、Fuel_Type统计年度汽车销量 - 按城市(比如Kolkata、Delhi)结合年份统计对应汽车销量
数据样例如下:
data.head().to_dict() {'S.No.': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}, 'Name': {0: 'Maruti Wagon R LXI CNG', 1: 'Hyundai Creta 1.6 CRDi SX Option', 2: 'Honda Jazz V', 3: 'Maruti Ertiga VDI', 4: 'Audi A4 New 2.0 TDI Multitronic'}, 'Location': {0: 'Mumbai', 1: 'Pune', 2: 'Chennai', 3: 'Chennai', 4: 'Coimbatore'}, 'Year': {0: 2010, 1: 2015, 2: 2011, 3: 2012, 4: 2013}, 'Kilometers_Driven': {0: 72000, 1: 41000, 2: 46000, 3: 87000, 4: 40670}, 'Fuel_Type': {0: 'CNG', 1: 'Diesel', 2: 'Petrol', 3: 'Diesel', 4: 'Diesel'}, 'Transmission': {0: 'Manual', 1: 'Manual', 2: 'Manual', 3: 'Manual', 4: 'Automatic'}, 'Owner_Type': {0: 'First', 1: 'First', 2: 'First', 3: 'First', 4: 'Second'}, 'Mileage': {0: '26.6 km/kg', 1: '19.67 kmpl', 2: '18.2 kmpl', 3: '20.77 kmpl', 4: '15.2 kmpl'}, 'Engine': {0: '998 CC', 1: '1582 CC', 2: '1199 CC', 3: '1248 CC', 4: '1968 CC'}, 'Power': {0: '58.16 bhp', 1: '126.2 bhp', 2: '88.7 bhp', 3: '88.76 bhp', 4: '140.8 bhp'}, 'Seats': {0: 5.0, 1: 5.0, 2: 5.0, 3: 7.0, 4: 5.0}, 'New_Price': {0: 5.51, 1: 16.06, 2: 8.61, 3: 11.27, 4: 53.14}, 'Price': {0: 1.75, 1: 12.5, 2: 4.5, 3: 6.0, 4: 17.74}}
期望的分组效果参考(以2013年首次车主的Honda Amaze S i-Dtech为例):
197,Honda Amaze S i-Dtech,Kolkata,2013,50000,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.25 346,Honda Amaze S i-Dtech,Kolkata,2013,57000,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.45 1662,Honda Amaze S i-Dtech,Delhi,2013,89429,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.65 1840,Honda Amaze S i-Dtech,Delhi,2013,90000,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.8 2953,Honda Amaze S i-Dtech,Kolkata,2013,38755,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.2 3438,Honda Amaze S i-Dtech,Kolkata,2013,39575,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.25 4740,Honda Amaze S i-Dtech,Bangalore,2013,61510,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,4.75 5403,Honda Amaze S i-Dtech,Kolkata,2013,46992,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,3.75 6626,Honda Amaze S i-Dtech,Kolkata,2013,51637,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54, 6692,Honda Amaze S i-Dtech,Chennai,2013,75000,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54, 7237,Honda Amaze S i-Dtech,Kolkata,2013,38568,Diesel,Manual,First,25.8 kmpl,1498 CC,98.6 bhp,5,8.54,
解决方案
问题根源
原代码绕了个弯路:先循环遍历Owner_Type的每个唯一值,再分别分组统计。这种操作完全冗余,当加入Name后,分组的组合数暴增,再加上循环带来的额外开销,直接导致超时或崩溃。正确的做法是直接对整个数据集做一次分组,不需要循环。
1. 按Year、Owner_Type、Name、Fuel_Type统计销量
# 用size()统计分组行数,比count()更高效(无需处理NaN) sales_by_car = data_cp.groupby(['Year', 'Owner_Type', 'Name', 'Fuel_Type'], as_index=False).size() # 把统计列名改成更直观的“销量” sales_by_car.rename(columns={'size': '销量'}, inplace=True) # 按年份升序、销量降序排序,方便查看每年的热门车型 sales_by_car.sort_values(['Year', '销量'], ascending=[True, False], inplace=True) # 查看前10条结果 print(sales_by_car.head(10))
2. 按城市+年度统计销量
# 按城市和年份分组统计 sales_by_city_year = data_cp.groupby(['Location', 'Year'], as_index=False).size() sales_by_city_year.rename(columns={'size': '销量'}, inplace=True) # 按城市名称和年份排序 sales_by_city_year.sort_values(['Location', 'Year'], ascending=True, inplace=True) # 查看前10条结果 print(sales_by_city_year.head(10))
3. 查看特定车型的详细分组数据
如果要像示例那样,查看某款车的所有原始记录,不需要用groupby,直接筛选即可:
# 筛选2013年、首次车主的Honda Amaze S i-Dtech target_data = data_cp[(data_cp['Name'] == 'Honda Amaze S i-Dtech') & (data_cp['Year'] == 2013) & (data_cp['Owner_Type'] == 'First')] # 按城市排序后输出 target_data.sort_values('Location', inplace=True) print(target_data)
额外优化建议
如果数据集特别大,可以先只保留需要的列再分组,减少内存占用:
# 只保留分组和统计必需的列 reduced_data = data_cp[['Year', 'Owner_Type', 'Name', 'Fuel_Type', 'Location']] # 再执行分组统计 sales_by_car = reduced_data.groupby(['Year', 'Owner_Type', 'Name', 'Fuel_Type']).size().reset_index(name='销量')
内容的提问来源于stack exchange,提问作者panda_newbie
相关产品推荐
相关产品推荐

