熊猫回填日期多指数的数据

时间:2016-06-02 16:27:47

标签: pandas

原始

user_id date        had_session made_an_order
1       2016-03-01  True        True
        2016-03-02  True        True
        2016-03-03  True        False

2       2016-03-01  True        True       
        2016-03-02  True        True       
        2016-03-04  True        False       

3       2016-03-01  True        False       
        2016-03-04  True        False       

回填数据

user_id date        had_session made_an_order
1       2016-03-01  True        True       
        2016-03-02  True        True       
        2016-03-03  True        False       
        2016-03-04  False       False     # backfilled row

2       2016-03-01  True        True       
        2016-03-02  True        True       
        2016-03-03  False       False    # backfilled row
        2016-03-04  True        False           

3       2016-03-01  True        False       
        2016-03-02  False       False           # backfilled row
        2016-03-03  False       False           # backfilled row
        2016-03-04  True        False       

我的数据有两个级别:第一级是user_id,第二级是他们是否有会话。

我想确保数据被回填,以便第二级包含每个可能的日期并默认为false

e.g。可能的日期是2016-03-01至2016-03-04。所以我想确保每个user_id都有这些日期

2 个答案:

答案 0 :(得分:2)

您可以先reset_index,然后pivot fillna,最后unstack

print (df.reset_index()
         .pivot(index='date',columns='user_id',values='had_session')
         .fillna(False)
         .unstack()
         .reset_index(name='had_session'))

    user_id        date had_session
0         1  2016-03-01        True
1         1  2016-03-02        True
2         1  2016-03-03        True
3         1  2016-03-04       False
4         2  2016-03-01        True
5         2  2016-03-02        True
6         2  2016-03-03       False
7         2  2016-03-04        True
8         3  2016-03-01        True
9         3  2016-03-02       False
10        3  2016-03-03       False
11        3  2016-03-04        True

说明:

#remove multiindex
print (df.reset_index())
   user_id        date had_session
0        1  2016-03-01        True
1        1  2016-03-02        True
2        1  2016-03-03        True
3        2  2016-03-01        True
4        2  2016-03-02        True
5        2  2016-03-04        True
6        3  2016-03-01        True
7        3  2016-03-04        True

#pivot table - get NaN in missing values
print (df.reset_index()
         .pivot(index='date',columns='user_id',values='had_session'))
user_id        1     2     3
date                        
2016-03-01  True  True  True
2016-03-02  True  True  None
2016-03-03  True  None  None
2016-03-04  None  True  True

#replace NaN to False
print (df.reset_index()
         .pivot(index='date',columns='user_id',values='had_session')
         .fillna(False))
user_id         1      2      3
date                           
2016-03-01   True   True   True
2016-03-02   True   True  False
2016-03-03   True  False  False
2016-03-04  False   True   True
#create multiindex         
print (df.reset_index()
         .pivot(index='date',columns='user_id',values='had_session')
         .fillna(False)
         .unstack())
user_id  date      
1        2016-03-01     True
         2016-03-02     True
         2016-03-03     True
         2016-03-04    False
2        2016-03-01     True
         2016-03-02     True
         2016-03-03    False
         2016-03-04     True
3        2016-03-01     True
         2016-03-02    False
         2016-03-03    False
         2016-03-04     True
dtype: bool

有2列的解决方案:

df1 = (df.reset_index()
         .pivot_table(index='date',columns='user_id',values=['had_session', 'made_an_order'])
         .fillna(False))

df2 = (df1.had_session)

df3 = (df1.made_an_order)

print (pd.concat([df2.unstack(),df3.unstack()], 
                 axis=1,
                 keys=['had_session','made_an_order']))
                   had_session made_an_order
user_id date                                
1       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03        True         False
        2016-03-04       False         False
2       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03       False         False
        2016-03-04        True         False
3       2016-03-01        True         False
        2016-03-02       False         False
        2016-03-03       False         False
        2016-03-04        True         False                 

另一个双pivot的解决方案:

df2 = (df.reset_index()
         .pivot(index='date',columns='user_id',values='had_session')
         .fillna(False))

df3 = (df.reset_index()
         .pivot(index='date',columns='user_id',values='made_an_order')
         .fillna(False))

print (pd.concat([df2.unstack(),df3.unstack()], 
                 axis=1,
                 keys=['had_session','made_an_order']))

                   had_session made_an_order
user_id date                                
1       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03        True         False
        2016-03-04       False         False
2       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03       False         False
        2016-03-04        True         False
3       2016-03-01        True         False
        2016-03-02       False         False
        2016-03-03       False         False
        2016-03-04        True         False  

答案 1 :(得分:1)

你可以这样做:

来源DF

In [370]: a
Out[370]:
                   had_session made_an_order
user_id date
1       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03        True         False
2       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-04        True         False
3       2016-03-01        True         False
        2016-03-04        True         False

使用MultiIndex准备DF,其中包含user_id和日期的产品:

In [371]: df = pd.DataFrame(
   .....:   index=pd.MultiIndex.from_product([
   .....:     a.index.get_level_values('user_id').unique().tolist(),
   .....:     a.index.get_level_values('date').unique().tolist()
   .....:   ])
   .....: )

从原始/源DF

设置索引名称
In [372]: df.index.names=a.index.names

加入

In [374]: df.join(a, how='left').fillna(False)
Out[374]:
                   had_session made_an_order
user_id date
1       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03        True         False
        2016-03-04       False         False
2       2016-03-01        True          True
        2016-03-02        True          True
        2016-03-03       False         False
        2016-03-04        True         False
3       2016-03-01        True         False
        2016-03-02       False         False
        2016-03-03       False         False
        2016-03-04        True         False