我有一个用户连接数据框,其中 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
我不确定我应该在这里采取什么方法。任何帮助表示赞赏。
答案 0 :(得分:3)
下面的代码应该会给你想要的结果。
第 1 步:创建一个 pd.Series 日期范围介于 01-01-2014 和 12-01-2020。
datelist = pd.date_range(start='01-01-2014', end='12-01-2020', freq='1d')
第 2 步:获取日期范围的长度。在我们的例子中,它是 2527。
nd = len(datelist)
第三步:获取原始UID唯一值的长度 数据框。在这个例子中,我们有 2
nu = len(df['UID'].unique())
第 4 步:创建一个包含两列的 DataFrame - UID 和 Date 用于 全范围 (2527 x 2)
df_final = pd.DataFrame({'UID':df['UID'].unique().tolist()*nd, 'Date':np.repeat(datelist,nu)})
第 5 步:现在将原始数据帧合并到 df_final
,以便您可以
获取分配给 #fans 的特定值。
df_final = df_final.merge(df, how='left')
第 6 步:按 UID 分组并向前填充行。如果他们是 不适用,将值设置为 0
df_final[['Date','#fans']] = df_final.groupby('UID')[['Date','#fans']].ffill().fillna(0)
第 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