我有一个数据框架如下:
import pandas as pd
#Data
data = {'Symbol':['MU', 'F', 'F', 'BX', 'BX', 'GE', 'BX', 'MU'],
'Date':['2018-08-20', '2018-08-21', '2018-08-22', '2018-08-24', '2018-08-25', '2018-08-27', '2018-08-27', '2018-08-27'],
'Quantity':[28, 30, 30, 3, 3, 5, 4, -28]}
# Create DataFrame
df = pd.DataFrame(data)
# Print the output.
df
Symbol Date Quantity
0 MU 2018-08-20 28
1 F 2018-08-21 30
2 F 2018-08-22 30
3 BX 2018-08-24 3
4 BX 2018-08-25 3
5 GE 2018-08-27 5
6 BX 2018-08-27 4
7 MU 2018-08-27 -28
我使用以下代码创建每个日期按符号的数量列的累计总和:
df1 = df.groupby(by=['Symbol','Date'])['Quantity'].sum().groupby(level='Symbol').cumsum().reset_index(name='Cumsum')
print (df1)
Symbol Date Cumsum
0 BX 2018-08-24 3
1 BX 2018-08-25 6
2 BX 2018-08-27 10
3 F 2018-08-21 30
4 F 2018-08-22 60
5 GE 2018-08-27 5
6 MU 2018-08-20 28
7 MU 2018-08-27 0
现在,对于每个符号,我想列出开始日期和结束日期之间的所有日期(或者今天,如果仍然保留),并将每个日期的最后一个数量向前拉。然后数据看起来像这样:
Symbol Date Quantity
BX 2018-08-24 3
BX 2018-08-25 6
BX 2018-08-26 6
BX 2018-08-27 10
F 2018-08-21 30
F 2018-08-22 60
F 2018-08-23 60
F 2018-08-24 60
F 2018-08-25 60
F 2018-08-26 60
F 2018-08-27 60
GE 2018-08-27 5
MU 2018-08-20 28
MU 2018-08-21 28
MU 2018-08-22 28
MU 2018-08-23 28
MU 2018-08-24 28
MU 2018-08-25 28
MU 2018-08-26 28
MU 2018-08-27 0
我该怎么做呢?
尝试先创建merge
,再创建merge
df.Date=pd.to_datetime(df.Date)
s = df.groupby('Symbol')['Date'].agg(['first','last'])
s['Date'] = [pd.date_range(x, y)for x, y in zip(s['first'],s['last'])]
out = s['Date'].explode().reset_index().merge(df,how='left').ffill()
out
Out[100]:
Symbol Date Cumsum
0 BX 2018-08-24 3.0
1 BX 2018-08-25 6.0
2 BX 2018-08-26 6.0
3 BX 2018-08-27 10.0
4 F 2018-08-21 30.0
5 F 2018-08-22 60.0
6 GE 2018-08-27 5.0
7 MU 2018-08-20 28.0
8 MU 2018-08-21 28.0
9 MU 2018-08-22 28.0
10 MU 2018-08-23 28.0
11 MU 2018-08-24 28.0
12 MU 2018-08-25 28.0
13 MU 2018-08-26 28.0
14 MU 2018-08-27 0.0
如果我们需要到最后日期8月27日
s = df.groupby('Symbol')['Date'].agg(['first'])
s['Date'] = [pd.date_range(x, max(df['Date']))for x in s['first']]
out = s['Date'].explode().reset_index().merge(df,how='left').ffill()
out
Out[102]:
Symbol Date Cumsum
0 BX 2018-08-24 3.0
1 BX 2018-08-25 6.0
2 BX 2018-08-26 6.0
3 BX 2018-08-27 10.0
4 F 2018-08-21 30.0
5 F 2018-08-22 60.0
6 F 2018-08-23 60.0
7 F 2018-08-24 60.0
8 F 2018-08-25 60.0
9 F 2018-08-26 60.0
10 F 2018-08-27 60.0
11 GE 2018-08-27 5.0
12 MU 2018-08-20 28.0
13 MU 2018-08-21 28.0
14 MU 2018-08-22 28.0
15 MU 2018-08-23 28.0
16 MU 2018-08-24 28.0
17 MU 2018-08-25 28.0
18 MU 2018-08-26 28.0
19 MU 2018-08-27 0.0
当你上次决定删除你的问题时,我已经起草了一个解决方案:)。
我认为你首先需要创建组合,然后合并/映射到原始数据框,并填充值,然后向前填充总和值。
首先从字符串
转换为日期df['Date'] = pd.to_datetime(df['Date']) #ignore if dtype is already datetime
:
dates = pd.date_range(df['Date'].min(),df['Date'].max(),freq='D')
comb = pd.MultiIndex.from_product((df['Symbol'].unique(),dates))
out = df.assign(cum_quant=df.groupby("Symbol")['Quantity'].cumsum()).merge(
pd.DataFrame(comb.tolist(),columns=['Symbol','Date']),on=['Symbol','Date'],how='right')
out = out.assign(Quantity=out.sort_values("Date").groupby("Symbol")['cum_quant'].ffill()
).dropna(subset=['Quantity']).drop("cum_quant",1)
这将为您提供结果,但是由于在最后一个问题中您的预期输出保留了符号的顺序,因此您可以使用pd.Categorical
来确保顺序。如果不需要,可以忽略此块。
cat_sym = pd.Categorical(out['Symbol'],categories=df['Symbol'].unique(),ordered=True)
out = out.assign(Symbol=cat_sym).sort_values(['Date','Symbol']).reset_index(drop=True)
print(out)
Symbol Date Quantity
0 MU 2018-08-20 28.0
1 MU 2018-08-21 28.0
2 F 2018-08-21 30.0
3 MU 2018-08-22 28.0
4 F 2018-08-22 60.0
5 MU 2018-08-23 28.0
6 F 2018-08-23 60.0
7 MU 2018-08-24 28.0
8 F 2018-08-24 60.0
9 BX 2018-08-24 3.0
10 MU 2018-08-25 28.0
11 F 2018-08-25 60.0
12 BX 2018-08-25 6.0
13 MU 2018-08-26 28.0
14 F 2018-08-26 60.0
15 BX 2018-08-26 6.0
16 MU 2018-08-27 0.0
17 F 2018-08-27 60.0
18 BX 2018-08-27 10.0
19 GE 2018-08-27 5.0