我有以下数据框:
name from amount days
A 7/31/18 200 1
B 7/31/18 300 1
C 7/30/18 200 1
D 7/27/18 100 3
......
G 7/17/18 50 1
H 7/13/18 150 4
我想将其扩展为天数不等于1的地方:
name from amount days
A 7/31/18 200 1
B 7/31/18 300 1
C 7/30/18 200 1
D 7/29/18 100 3
D 7/28/18 100 3
D 7/27/18 100 3
......
G 7/17/18 50 1
H 7/16/18 150 4
H 7/15/18 150 4
H 7/14/18 150 4
H 7/13/18 150 4
如果可能的话,我还想添加一列以区分原始数据和扩展数据(因为最终我将需要过滤一些日期):
name from amount days original
A 7/31/18 200 1 1
B 7/31/18 300 1 1
C 7/30/18 200 1 1
D 7/29/18 100 3 0
D 7/28/18 100 3 0
D 7/27/18 100 3 1
......
G 7/17/18 50 1 1
H 7/16/18 150 4 0
H 7/15/18 150 4 0
H 7/14/18 150 4 0
H 7/13/18 150 4 1
编辑:要澄清扩展:天将告诉您需要扩展到多少行。或者,您可以使用原始值上方的日期作为边界(条目7/27(天数= 3)将在上面的值(日期为7/30处停止)。数据具有约束条件以确保其永不重叠)。
答案 0 :(得分:3)
df['from'] = pd.to_datetime(df['from'])
pd.DataFrame([
(n, f, a, d, int(f == F))
for n, F, a, d in zip(*map(df.get, df))
for f in pd.date_range(F, periods=d)[::-1]
], columns=[*df.columns] + ['original'])
name from amount days original
0 A 2018-07-31 200 1 1
1 B 2018-07-31 300 1 1
2 C 2018-07-30 200 1 1
3 D 2018-07-29 100 3 0
4 D 2018-07-28 100 3 0
5 D 2018-07-27 100 3 1
6 G 2018-07-17 50 1 1
7 H 2018-07-16 150 4 0
8 H 2018-07-15 150 4 0
9 H 2018-07-14 150 4 0
10 H 2018-07-13 150 4 1
我将答案编辑为使用duplicated
而不是cum_count
。我是从@Wen's post
def f(x):
return pd.date_range(
pd.to_datetime(x).min(),
periods=len(x)
).sort_values(ascending=False)
def g(d):
return d.groupby('name')['from'].transform(f)
def h(d):
return 1 - d.name.duplicated(keep='last')
df.loc[df.index.repeat(df.days)].assign(**{'from': g, 'original': h})
name from amount days original
0 A 2018-07-31 200 1 1
1 B 2018-07-31 300 1 1
2 C 2018-07-30 200 1 1
3 D 2018-07-29 100 3 0
3 D 2018-07-28 100 3 0
3 D 2018-07-27 100 3 1
4 G 2018-07-17 50 1 1
5 H 2018-07-16 150 4 0
5 H 2018-07-15 150 4 0
5 H 2018-07-14 150 4 0
5 H 2018-07-13 150 4 1
答案 1 :(得分:3)
大约分两步创建数据框(reindex
)并调整值(duplicated
)
newdf=df.reindex(df.index.repeat(df.days)) # create the df using reindex
adddate=pd.Series(np.concatenate(df.days.apply(np.arange).values),index=newdf.index)# create the timedelta to add
newdf['from']=pd.to_datetime(newdf['from'])+pd.to_timedelta(adddate,unit='d')# assign the value
newdf['original']=(~newdf.index.duplicated()).astype(int)
newdf
Out[240]:
name from amount days original
0 A 2018-07-31 200 1 1
1 B 2018-07-31 300 1 1
2 C 2018-07-30 200 1 1
3 D 2018-07-27 100 3 1
3 D 2018-07-28 100 3 0
3 D 2018-07-29 100 3 0