我有一个与此类似的数据框,其中包含枚举日期和ID,以及在给定日期和ID下售出的商品数量:
Date ID num_sold
0 1 0
2 13
1 1 6
2 0
2 1 0
2 0
3 1 5
2 4
对于每个ID,我想计算上次销售发生的日期。所以我有以下数据框:
Date ID num_sold last_sale
0 1 0 -1
2 13 -1
1 1 6 -1
2 0 0
2 1 0 1
2 0 0
3 1 5 1
2 4 0
我想计算列last_sale
,其中1和0是给定ID
时的日期值,num_sold
最后为非零值。如果没有这样的最后日期(例如,数据集中的第一个月),则为-1(或者可以是nan)。
在给定的示例中,
在第1天,ID 1从未被出售过,因此我们将last_sale
设置为-1。 ID 2最近一次在第0个月售出,因此我们将last_sale
设置为0。
同样,在第3天,ID 1在第1个月最后一次出售,因此last_sale
为1,ID 2在第0个月最后出售,因此last_sale
为0。
最有效,最简洁的方法是什么?
答案 0 :(得分:2)
首先,您需要为当前销售日期创建一列:
df["current_sale_date"] = 0
df.loc[df.num_sold != 0, "current_sale_date"] = df.Date
您为上次销售日期创建另一列。首先,将0替换为np.nan,以使.ffill()起作用。然后,对于每个ID,您都可以通过.fill()获得当前销售日期的值。
df.current_sale_date = df.current_sale_date.replace(0, np.nan)
df["last_sale_date"] = df.groupby(['ID'])['current_sale_date'].ffill()
然后您将获得按ID排班的以前的销售日期
df.last_sale_date = df.groupby(['ID'])['last_sale_date'].shift()
对于第一个日期,您设置-1
df.loc[df.Date == df.Date.idxmin(), "last_sale_date"] = -1
您将nan替换回0,因为0是一个日期
df.last_sale_date = df.last_sale_date.replace(np.nan, 0)
第一次出售ID,如果没有以前的销售日期,则设置-1
df.loc[(df.current_sale_date == 1) & (df.last_sale_date == 0), "last_sale_date"] = -1
答案 1 :(得分:1)
首先,让我们创建您的DataFrame df1。
import pandas as pd
df1 = pd.DataFrame({'Date': ['0', '0', '1', '1', '2', '2', '3', '3'],
'ID': ['1', '2', '1', '2', '1', '2', '1', '2'],
'num_sold': [0, 13, 6, 0, 0, 0, 5, 4]})
print(df1)
输出:
Date ID num_sold
0 0 1 0
1 0 2 13
2 1 1 6
3 1 2 0
4 2 1 0
5 2 2 0
6 3 1 5
7 3 2 4
现在,我们将其按ID分组,将您的逻辑应用于每个ID组,然后将这些组连接起来。
groups = []
for name, group in df1.groupby(['ID']):
group.loc[group['num_sold'].shift(1)!=0, 'last_sale'] = group['Date'].shift(1)
group['last_sale'] = group['last_sale'].fillna(method='ffill').fillna('-1')
groups.append(group)
df2 = pd.concat(groups).sort_values(['Date', 'ID'])
print(df2)
您的结果:
Date ID num_sold last_sale
0 0 1 0 -1
1 0 2 13 -1
2 1 1 6 -1
3 1 2 0 0
4 2 1 0 1
5 2 2 0 0
6 3 1 5 1
7 3 2 4 0
祝你好运!