我有一个像下面这样的 Pandas 数据框
buyer_id item_id order_id date qty_purchased qty_bought
210 82 470 2016-01-02 5 1
169 57 475 2016-01-02 5 1
169 83 475 2016-01-02 5 1
228 82 520 2016-01-03 4 1
228 86 520 2016-01-03 4 1
228 90 520 2016-01-03 4 1
229 57 521 2016-01-03 4 1
232 82 525 2016-01-04 4 3
210 90 526 2016-01-04 4 1
210 91 526 2016-01-04 5 1
210 15 526 2016-01-05 5 1
233 90 527 2016-01-05 4 1
我想找到每个日期推出的 item_id
,如果 item_id 在超过 1 个日期推出,那么我想找到每个日期的 `(qty_bought/qty_purchased) 的比率。
我想要的输出如下
Item_id date 1st Introduced Ratio Date 2nd Introduced Ratio Date 3rd Introduced Ratio Flag
82 2016-01-02 1/5 2016-01-03 1/4 2016-01-04 3/4 1
标志的条件是当比率大于以前的日期时,则应将其设置为 1,否则应设置为 0
如果我在 5 个不同的日期引入了项目,那么这应该动态生成 5 个日期和比率列。比率将特定于该日期。我只想列出那些不止一次介绍过的item_id
。
这是我在python中的尝试
df.groupby('item_id')['date'].apply(lambda x: np.unique(x.tolist()))
这为我提供了 item_id
列表及其引入日期。现在,如果该项目在超过 1 个日期推出,我想在上面进行子集化。
df.groupby('item_id').apply(lambda r: r['date'].unique().shape[0] > 1)
这为我提供了超过 1 个日期的所有 item_id
。但是我不知道如何制作具有所需输出的数据框以及如何根据引入它们的日期动态添加 date & ratio
列。请帮忙
最佳答案
此问题的第一部分是选择那些具有包含多个日期的item_id
的行,并创建仅包含这些项目的新日期框。
#subset the items which have more than one date
items_1 = df.groupby('item_id').filter(lambda x: len(np.unique(x['date']))>1).item_id
#create a new dataframe with just those items that have more than one date
new_df = df[df['item_id'].isin(items_1)].copy()
#create the ratio columns
new_df['ratio'] = new_df['qty_bought']/new_df['qty_purchased']
#delete the columns that are not required
new_df.drop(['order_id', 'buyer_id','qty_purchased', 'qty_bought'], axis = 1, inplace= True)
item_id date ratio
0 82 2016-01-02 0.20
1 57 2016-01-02 0.20
3 82 2016-01-03 0.25
5 90 2016-01-03 0.25
6 57 2016-01-03 0.25
7 82 2016-01-04 0.75
8 90 2016-01-04 0.25
11 90 2016-01-05 0.25
问题的第二部分是每个唯一的item_id
只有一行,对应的日期和比例有多个列。我们使用 groupby
来获取每个 item_id
的条目,然后是 iterate通过它的 date
和 ratio
值,同时将它们添加到 dateframe 中新创建的列。
#group by items and grab each date after the first and insert in a new column
for name, group in new_df.groupby('item_id'):
for i in range(1, len(group)):
new_df.loc[group.index[0], 'date'+str(i+1)] = group.date.iloc[i]
new_df.loc[group.index[0], 'ratio'+str(i+1)] = group.ratio.iloc[i]
#delete the original date column since that information was replicated
new_df.drop(['date', 'ratio'], axis =1, inplace=True)
#keep only one row for each `item_id`
new_df.dropna(subset = ['date0'])
item_id date ratio date2 ratio2 date3 ratio3
0 82 2016-01-02 0.20 2016-01-03 0.25 2016-01-04 0.75
1 57 2016-01-02 0.20 2016-01-03 0.25 NaN NaN
5 90 2016-01-03 0.25 2016-01-04 0.25 2016-01-05 0.25
关于python - groupby 并将键的所有值放在一行中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35531822/