2017-01-09 72 views
3

我有大约运行的各种促销活动和他们的开始日期,结束日期的信息的推广说明数据集:数据操作开始日期结束日期蟒蛇熊猫

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

可以使用concat通过date_rangeitertuples创建的所有Series秒,然后joinpromoitem

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 

meltgroupby with resample另一种解决方案:

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

您可以让非日期列采用索引轴,因为它们在任何更改m的方向上都会发生变化适用于日期列。这在分组操作中会很方便。

指定append=True有助于跟踪哪些原DF之前所拥有的索引。 stack它们从而使START_DATEEND_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) 

同样,构造新的数据帧具有它是如下面所定义的值和索引这个时候。由于索引是对齐的,我们可以沿着它们的两个数据帧。

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

enter image description here

1

不介意我。我只是想numpy -fy这个问题/答案

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 
相关问题