数据操作startdate enddate python pandas

时间:2017-01-09 07:12:32

标签: python pandas

我有一个促销描述数据集,其中包含有关各种促销活动及其开始日期结束日期的信息:

promo        item      start_date      end_date 

Buy1-get 1     A        2015-01-08    2015-01-12

Buy1-get 1     A        2015-02-16    2015-02-20

Buy1-40% off   B        2016-05-08      2016-05-09

现在我想组织我的数据进行后续分析,以便我只有一个可变日期和促销信息。

date            item       Promo

2015-01-08       A         Buy1-get 1 

2015-01-09       A         Buy1-get 1 
2015-01-10       A         ......
2015-01-11       ....
2015-01-12

2015-02-16       A         Buy1-get 1 
2015-02-17       A         Buy1-get 1 
2015-02-18       ....      .......
2015-02-19       .....

..........
2016-05-09       B         Buy1-40% off

任何帮助都会非常感激。

3 个答案:

答案 0 :(得分:3)

您可以CSJ2K使用concat创建所有Series date_range,然后使用itertuplespromoitem

df1 = pd.concat([pd.Series(r.Index,
                           pd.date_range(r.start_date,r.end_date)) for r in df.itertuples()])
        .reset_index()
df1.columns = ['date','idx']
df1 = df1.set_index('idx')
df1 = df1.join(df[['item','promo']]).reset_index(drop=True)
print (df1)
         date item         promo
0  2015-01-08    A    Buy1-get 1
1  2015-01-09    A    Buy1-get 1
2  2015-01-10    A    Buy1-get 1
3  2015-01-11    A    Buy1-get 1
4  2015-01-12    A    Buy1-get 1
5  2015-02-16    A    Buy1-get 1
6  2015-02-17    A    Buy1-get 1
7  2015-02-18    A    Buy1-get 1
8  2015-02-19    A    Buy1-get 1
9  2015-02-20    A    Buy1-get 1
10 2016-05-08    B  Buy1-40% off
11 2016-05-09    B  Buy1-40% off

joinmelt的另一种解决方案:

df1 = df.reset_index().rename(columns={'index':'idx'})
df1 = pd.melt(df1, id_vars='idx', value_vars=['start_date','end_date'], value_name='date')
        .set_index('date')
df1 = df1.groupby('idx')
         .resample('d')
         .ffill()
         .reset_index(level=1)
         .drop(['idx','variable'], axis=1)
df1 = df1.join(df[['item','promo']]).reset_index(drop=True)
print (df1)
         date item         promo
0  2015-01-08    A    Buy1-get 1
1  2015-01-09    A    Buy1-get 1
2  2015-01-10    A    Buy1-get 1
3  2015-01-11    A    Buy1-get 1
4  2015-01-12    A    Buy1-get 1
5  2015-02-16    A    Buy1-get 1
6  2015-02-17    A    Buy1-get 1
7  2015-02-18    A    Buy1-get 1
8  2015-02-19    A    Buy1-get 1
9  2015-02-20    A    Buy1-get 1
10 2016-05-08    B  Buy1-40% off
11 2016-05-09    B  Buy1-40% off

答案 1 :(得分:1)

您可以让非日期列占据索引轴,因为它们会在w.r.t方向上发生变化,这些更改会对日期列进行任何更改。这在分组操作期间会很方便。

指定append=True有助于跟踪原始DF之前的索引。 stack他们,以便 start_date end_date 相互低于。

mi_ser = df.set_index(['promo', 'item'], append=True).stack()
grouper = mi_df.index.get_level_values(0)

构造一个新的Series,其值和索引与我们之前的多索引系列对象中的值相同。

执行groupby w.r.t第一个索引级别并根据每日频率重新取样值,并选择与datetime值兼容的任何形式的聚合函数。 [此处,first被选中]

s = pd.Series(mi_ser.values, mi_ser.values).groupby(grouper).resample('D').first()
idx, val = s.index.get_level_values(0), s.index.get_level_values(1)

同样,这次构建一个新的数据框,其中包含如下定义的值和索引。 由于索引是对齐的,我们可以join沿着它们的两个数据帧。

pd.DataFrame(val, idx, ['date']).join(df[['item', 'promo']]).reset_index(drop=True)

enter image description here

答案 2 :(得分:1)

别介意我。我只想numpy - 问这个问题/答案

day = int(60 * 60 * 24 * 1e9)

sd = df.start_date.values
ed = df.end_date.values
dd = ed - sd
ds = (dd / day).astype(int) + 1

sdays = ds.sum()
cdays = ds.cumsum()
rng = np.arange(sdays)
slc = np.roll(cdays % sdays, 1)
add = rng - rng[slc].repeat(ds)

d1 = pd.DataFrame(dict(
        promo=df.promo.values.repeat(ds),
        item=df.item.values.repeat(ds),
    ), pd.Index(sd.repeat(ds) + add * day, name='date'))

print(d1)

           item         promo
date                         
2015-01-08    A    Buy1-get 1
2015-01-09    A    Buy1-get 1
2015-01-10    A    Buy1-get 1
2015-01-11    A    Buy1-get 1
2015-01-12    A    Buy1-get 1
2015-02-16    A    Buy1-get 1
2015-02-17    A    Buy1-get 1
2015-02-18    A    Buy1-get 1
2015-02-19    A    Buy1-get 1
2015-02-20    A    Buy1-get 1
2016-05-08    B  Buy1-40% off
2016-05-09    B  Buy1-40% off