python 如何筛选出每个item_id的最新和最早日期的行?

ao218c7q  于 2023-06-28  发布在  Python
关注(0)|答案(5)|浏览(84)

我想使用pandas过滤出每个item_id的最新和最早日期的行。提前感谢您的帮助:)
| 最喜欢的|日期| date |
| - -----|- -----| ------------ |
| 八|2022-06-09 2022-06-09| 2022-06-09 |
| 八|2022-06- 10 2022-06-10 2022-06-10| 2022-06-10 |
| 八|2022-06-11 2022-06-11 2022-06-11| 2022-06-11 |
| 八|2022-06- 12 2022-06-12 2022-06-12| 2022-06-12 |
| 一百六十八|2022-06-09 2022-06-09| 2022-06-09 |
| 一百六十八|2022-06- 10 2022-06-10 2022-06-10| 2022-06-10 |
| 一百六十八|2022-06-11 2022-06-11 2022-06-11| 2022-06-11 |
| 一百六十八|2022-06- 12 2022-06-12 2022-06-12| 2022-06-12 |
| 一百六十八|2022-06-13 2022-06-13 2022-06-13| 2022-06-13 |
理想输出为:
| 最喜欢的|日期| date |
| - -----|- -----| ------------ |
| 八|2022-06-09 2022-06-09| 2022-06-09 |
| 八|2022-06- 12 2022-06-12 2022-06-12| 2022-06-12 |
| 一百六十八|2022-06-09 2022-06-09| 2022-06-09 |
| 一百六十八|2022-06-13 2022-06-13 2022-06-13| 2022-06-13 |
原始数据在这里:

item_id,favorite,date
1049977,8,2022-06-09
1049977,8,2022-06-10
1049977,8,2022-06-11
1049977,8,2022-06-12
1611924,168,2022-06-09
1611924,168,2022-06-10
1611924,168,2022-06-11
1611924,168,2022-06-12
1611924,168,2022-06-13
1l5u6lss

1l5u6lss1#

df[df.groupby('item_id')['date'].transform(lambda x: x.eq(x.max()) | x.eq(x.min()))]

输出:

item_id  favorite       date
0  1049977         8 2022-06-09
3  1049977         8 2022-06-12
4  1611924       168 2022-06-09
8  1611924       168 2022-06-13
unhi4e5o

unhi4e5o2#

这最好使用groupby操作来完成。在开始时,使用循环执行此操作可能很有吸引力,但随着行数的增加,这将严重影响性能。
使用groupby方法.first()和.last()给出了第一个和最后一个条目。请注意,您需要确保您的dataframe按指定日期的任何列进行排序。
.concat只是一种将结果放在一个df中的简单方法。也许还有更好的选择。
这个片段:

pd.concat([
    df.groupby('item_id').first(),
    df.groupby('item_id').last()
    ]).sort_index()

给我这个输出:

favorite        date
item_id                      
1049977         8  2022-06-09
1049977         8  2022-06-12
1611924       168  2022-06-09
1611924       168  2022-06-13
4c8rllxm

4c8rllxm3#

您可以在groupby.applytransform(min)transform(max)中使用最大值、最小值date过滤组

out = (df.groupby('item_id')
       .apply(lambda g: g[g['date'].isin([g['date'].min(), g['date'].max()])])
       .reset_index(drop=True))

# or

groups = df.groupby(['item_id'])['date']
out = df[(df['date']==groups.transform(min)) | (df['date']==groups.transform(max))]
print(out)

   item_id  favorite        date
0  1049977         8  2022-06-09
3  1049977         8  2022-06-12
4  1611924       168  2022-06-09
8  1611924       168  2022-06-13
x6yk4ghg

x6yk4ghg4#

这里有一个不需要对输入 Dataframe 进行排序的解决方案。对于每个item_id,它获取日期最早(最小)或最晚(最大)的行的索引值,然后使用这些索引值过滤原始 Dataframe 。

df.iloc[df.groupby('item_id').date.agg(['idxmin','idxmax']).values.ravel()]

    item_id favorite          date
0   1049977        8    2022-06-09
3   1049977        8    2022-06-12
4   1611924      168    2022-06-09
8   1611924      168    2022-06-13
vhipe2zx

vhipe2zx5#

替代方法:

df=pd.DataFrame({'item_id': [1049977, 1049977, 1049977, 1049977,1611924,1611924,1611924,1611924,1611924],
                 'favorite': [8,8,8,8,168,168,168,168,168],
                 'date': ['2022-06-09', '2022-06-10', '2022-06-11', '2022-06-12',
                          '2022-06-09', '2022-06-10', '2022-06-11', '2022-06-12', '2022-06-13']})

df['date'] = pd.to_datetime(df['date'])

df['nrows'] = df.groupby(['item_id', 'favorite']).cumcount()+1

df['max_row'] = df.groupby(['item_id', 'favorite'])['nrows'].transform('max')
df['min_row'] = df.groupby(['item_id', 'favorite'])['nrows'].transform('min')

df['flag_min'] = df.apply(lambda x: 1 if (x['nrows']==x['min_row']) else 0, axis = 1)
df['flag_max'] = df.apply(lambda x: 1 if (x['nrows']==x['max_row']) else 0, axis = 1)

df1 = df[(df['flag_min']== 0) & (df['flag_max']== 0)].drop(['nrows','max_row', 'min_row', 'flag_min', 'flag_max'], axis = 1)

print(df1)

相关问题