Pandas宽格式数据:提取各图书最早两个季度的有效销售数据
处理宽格式DataFrame:提取每本图书最早两个有数据的季度销售数据
问题背景
现有宽格式销售数据DataFrame,记录不同图书的季度销量,未发布季度以0填充。需要为每本图书提取最早的两个有有效销量的季度,并将对应数据存入新DataFrame的两列中。
示例数据
import pandas as pd data = {'Book Title': ['A Court of Thorns and Roses', 'Where the Crawdads Sing', 'Bad Blood', 'Atomic Habits'], 'Metric': ['Book Sales','Book Sales','Book Sales','Book Sales'], 'Q1 2022': [100000,0,0,0], 'Q2 2022': [50000,75000,0,35000], 'Q3 2022': [25000,150000,20000,45000], 'Q4 2022': [25000,20000,10000,65000]} df1 = pd.DataFrame(data)
实现步骤与代码
1. 转换为长格式数据
把宽格式的季度列转为行结构,方便按图书分组处理:
# 保留图书名称和度量列,将季度列转为长格式 df_long = df1.melt(id_vars=['Book Title', 'Metric'], var_name='Quarter', value_name='Sales')
2. 过滤无效数据并按季度排序
过滤掉销量为0的无效行,再按图书分组,对每个组的季度按时间顺序排序,取前两个有效记录:
# 过滤销量为0的行 df_filtered = df_long[df_long['Sales'] != 0] # 按图书分组,对每组的季度排序后取前两个 # 注:Q1/Q2/Q3/Q4+年份的字符串格式天然有序,可直接排序 df_top2 = df_filtered.groupby('Book Title').apply(lambda x: x.sort_values('Quarter').head(2)).reset_index(drop=True)
3. 转换回宽格式生成目标DataFrame
把每个图书的前两个季度数据转为两列,让结果更直观:
# 给每个图书的有效季度添加序号(第1/2个) df_top2['Rank'] = df_top2.groupby('Book Title').cumcount() + 1 # 转换为宽格式 result_df = df_top2.pivot(index=['Book Title', 'Metric'], columns='Rank', values=['Quarter', 'Sales']).reset_index() # 重命名列名 result_df.columns = ['Book Title', 'Metric', 'First Quarter', 'Second Quarter', 'First Sales', 'Second Sales']
4. 查看最终结果
print(result_df)
输出示例:
Book Title Metric First Quarter Second Quarter First Sales Second Sales 0 Atomic Habits Book Sales Q2 2022 Q3 2022 35000 45000 1 Bad Blood Book Sales Q3 2022 Q4 2022 20000 10000 2 A Court of Thorns and Roses Book Sales Q1 2022 Q2 2022 100000 50000 3 Where the Crawdads Sing Book Sales Q2 2022 Q3 2022 75000 150000
注意事项
- 如果原始数据的空值是
NaN而非0,只需把过滤条件改成df_long[df_long['Sales'].notna()] - 若季度格式不是
Qx YYYY,需先转为时间格式再排序,示例代码:
排序后可再转回原字符串格式。df_filtered['Quarter'] = pd.to_datetime(df_filtered['Quarter'].str.replace('Q', ''), format='%m %Y')
内容的提问来源于stack exchange,提问作者Tyler Moore
相关产品推荐
相关产品推荐

