我有一个包含 date
、value
和 isoweek
字段的数据框,如下所示:
date | value | isoweek
-----------------------------
2018-04-01 | 5 | 2018-13
2018-04-10 | 10 | 2018-15
2018-05-01 | 10 | 2018-18
其中 isoweek
是相应日期的年-周。我的目标是迭代 isoweeks,找到数据中不存在的 isoweeks,然后将一行插入到数据框中,以 0
作为值。
预期的输出如下所示:
date | value | isoweek
-----------------------------
2018-04-01 | 5 | 2018-13
NaN | 0 | 2018-14
2018-04-10 | 10 | 2018-15
NaN | 0 | 2018-16
NaN | 0 | 2018-17
2018-05-01 | 10 | 2018-18
如何遍历原始数据框,并找到数据中所有缺失的等值周?
答案 0 :(得分:2)
您可以使用 pandas.date_range() 生成每周从 start
到 end
的日期列表。
dates = pd.Series(pd.date_range(start=df['date'].min(), end=df['date'].max(), freq='W'))
isoweeks = (dates.dt.isocalendar().year.astype(str) + '-' + dates.dt.isocalendar().week.astype(str)).tolist()
max_isoweek = str(df['date'].max().isocalendar()[0]) + '-' + str(df['date'].max().isocalendar()[1])
if max_isoweek not in isoweeks:
isoweeks.append(max_isoweek)
这是获取 start
日期和 end
日期之间的所有 iso 周。
然后你可以将 df 合并到一个辅助数据帧中以获得你想要的。
df = df.merge(pd.DataFrame({'isoweek': isoweeks}), how='right')
df['value'].fillna(0, inplace=True)
# print(df)
date value isoweek
0 2018-04-01 5.0 2018-13
1 NaT 0.0 2018-14
2 2018-04-10 10.0 2018-15
3 NaT 0.0 2018-16
4 NaT 0.0 2018-17
5 2018-05-01 10.0 2018-18
答案 1 :(得分:1)
也许有点冗长,但您可以在将 isoweek 转换为日期后尝试使用 resample
:
s = pd.to_datetime(df['isoweek']+"-0",format='%Y-%W-%w')
u = df.set_index(s).resample("W").first()
iso_week = u.index.year.astype(str)+'-'+u.index.weekofyear.astype(str)
u['isoweek'] = u['isoweek'].fillna(pd.Series(iso_week,index=u.index))
out = u.fillna({"value":0}).reset_index(drop=True)
print(out)
date value isoweek
0 2018-04-01 5.0 2018-13
1 NaN 0.0 2018-14
2 2018-04-10 10.0 2018-15
3 NaN 0.0 2018-16
4 NaN 0.0 2018-17
5 2018-05-01 10.0 2018-18
答案 2 :(得分:1)
您可以尝试使用 apply
:
def func(row):
year = (row.name)
r = row['isoweek'].str.split('-').str[1].astype(int)
min_week = min(r)
max_week = max(r)
val_range = range(min_week, max_week)
missing = (set(val_range) - set(r.values))
for mis_week in missing:
row = (row.append({'isoweek': f"{year}-{mis_week}", 'date': np.nan, 'value':0}, ignore_index=True))
return (row.sort_values(by='isoweek').reset_index(drop=True))
df.groupby(df.isoweek.str.split('-').str[0],as_index=False).apply(func)
date value isoweek
0 0 2018-04-01 5 2018-13
1 NaN 0 2018-14
2 2018-04-10 10 2018-15
3 NaN 0 2018-16
4 NaN 0 2018-17
5 2018-05-01 10 2018-18