【问题标题】:groupby and put all values of a key in one rowgroupby 并将键的所有值放在一行中
【发布时间】:2016-06-02 14:11:40
【问题描述】:

我有一个如下所示的熊猫数据框

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 在多个日期引入,那么我想找到每个日期的 `(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 列。请帮忙

【问题讨论】:

  • 我不明白标志的用途,如果有三个日期,以及比率从日期 1 到日期 2 增加但从日期 2 到日期 3 减少。会发生什么?跨度>
  • @imp9 如果第三个日期的比率大于第二个日期,则标志将设置为 1。
  • i@imp9 我想要有问题的输出。但不知道如何使数据框看起来像这样
  • 我已经更新了我的解决方案。

标签: python pandas


【解决方案1】:

此问题的第一部分是选择具有多个日期的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 的条目,然后通过iteratedateratio 值获取条目,同时将它们添加到日期帧中新创建的列中。

#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

【讨论】:

  • 我不想要重复的日期,难道我们不能有唯一的日期吗?所以在上面的输出中2016-01-02 应该只显示一次。
  • 我已经编辑了 for 循环,以便我们只添加该行中尚未包含的日期。如果您想重命名第一个日期和比率列,请查看renaming columns。如果还有其他事情,请告诉我。
  • 太棒了.. 非常感谢.. 我只想再添加一个列来计算两个日期之间的天数差异 (date2-date1) 如果有 3 个日期列,那么 (date2-date1) & (date3-date2)
  • 要添加一列,只需执行newdf['new_col_name']。接下来使用 for 循环并利用这样一个事实,即当只有 2 个日期时,date3 有一个 NaN。当有三个日期时,日期 3 没有 NaN。pandas.notnull()pandas.isnull() 将帮助选择这些行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 2023-03-28
  • 2021-01-17
  • 1970-01-01
相关资源
最近更新 更多