为每个日期展开数据框 |熊猫

时间:2021-02-04 05:01:22

标签: pandas dataframe

我有一个用户连接数据框,其中 UID 表示用户,日期表示用户建立连接的日期(由 #fans 表示)。

UID     Date        #fans
9305    1/25/2015   5
9305    2/26/2015   7
9305    3/27/2015   8
9305    4/1/2015    9
1305    6/6/2015    14
1305    6/26/2015   16
1305    6/27/2015   17

数据框的日期范围是 01-01-2014 到 12-01-2020。

我需要扩展数据,以便对于每个用户,日期应该包含日期范围内的每个日期,并且每个日期都应该有 #fans 作为用户在该日期之前的总连接数。 例如所需的输出是

UID     Date        #fans
9305    1/1/2014    0
9305    1/2/2014    0
9305    1/3/2014    0
...
9305    1/25/2015   5
9305    1/26/2015   5
9305    1/27/2015   5
...
9305    2/26/2015   7
9305    3/27/2015   8
9305    3/28/2015   8
9305    3/29/2015   8
...
9305    4/1/2015    9
...
9305    12/1/2020   9

*for all the UIDs

我不确定我应该在这里采取什么方法。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:3)

下面的代码应该会给你想要的结果。

  1. 第 1 步:创建一个 pd.Series 日期范围介于 01-01-2014 和 12-01-2020。

    datelist = pd.date_range(start='01-01-2014', end='12-01-2020', freq='1d')

  2. 第 2 步:获取日期范围的长度。在我们的例子中,它是 2527。

    nd = len(datelist)

  3. 第三步:获取原始UID唯一值的长度 数据框。在这个例子中,我们有 2

    nu = len(df['UID'].unique())

  4. 第 4 步:创建一个包含两列的 DataFrame - UID 和 Date 用于 全范围 (2527 x 2)

    df_final = pd.DataFrame({'UID':df['UID'].unique().tolist()*nd, 'Date':np.repeat(datelist,nu)})

  5. 第 5 步:现在将原始数据帧合并到 df_final,以便您可以 获取分配给 #fans 的特定值。

    df_final = df_final.merge(df, how='left')

  6. 第 6 步:按 UID 分组并向前填充行。如果他们是 不适用,将值设置为 0

    df_final[['Date','#fans']] = df_final.groupby('UID')[['Date','#fans']].ffill().fillna(0)

  7. 第 7 步:最后,我们将 #fans 的 dtype 更改为 int 否则 值将与 xx.0 浮动

    df_final['#fans'] = df_final['#fans'].astype('int64')

将所有这些放在一起,代码如下:

import pandas as pd
import numpy as np
from datetime import datetime

c = ['UID','Date','#fans']
d = [[9305,    '1/25/2015',   5],
[9305,    '2/26/2015',  7],
[9305,    '3/27/2015',   8],
[9305,    '4/1/2015',    9],
[1305,    '6/6/2015',   14],
[1305,    '6/26/2015',   16],
[1305,    '6/27/2015',   17]]
df = pd.DataFrame(d,columns=c)
df.Date = pd.to_datetime(df.Date)
print (df)

datelist = pd.date_range(start='01-01-2014', end='12-01-2020', freq='1d')
nd = len(datelist)
nu = len(df['UID'].unique())

df_final = pd.DataFrame({'UID':df['UID'].unique().tolist()*nd,
                         'Date':np.repeat(datelist,nu)})

df_final = df_final.merge(df, how='left')

df_final[['Date','#fans']] = df_final.groupby('UID')[['Date','#fans']].ffill().fillna(0)

df_final['#fans'] = df_final['#fans'].astype('int64')
print (df_final)

输出结果为:

       UID       Date  #fans
1     1305 2014-01-01      0
3     1305 2014-01-02      0
5     1305 2014-01-03      0
7     1305 2014-01-04      0
9     1305 2014-01-05      0
...    ...        ...    ...
5044  9305 2020-11-27      9
5046  9305 2020-11-28      9
5048  9305 2020-11-29      9
5050  9305 2020-11-30      9
5052  9305 2020-12-01      9

上面的代码还考虑了从一个 UID 到另一个 UID 的转换。

代码将确保以下内容:

       UID       Date  #fans
2526  1305 2020-12-01     17
       UID       Date  #fans
2527  9305 2014-01-01      0