我有下面的数据帧,我想在其中获得缺失的日期及其在panda中的键。
size number key date
0 153.2 K 12345 Hello 20181001
1 153.2 K 12345 No 20181001
2 153.2 K 12345 Hello 20181003
3 153.2 K 12345 No 20181003
4 153.2 K 12345 Hello 20181004
5 153.2 K 12345 No 20181004
我希望输出为,
key date
Hello 20181002
No 20181002
提前感谢
你可以通过一些像这样的花式重塑来做到这一点:
(df.pivot('date', 'key')
.reindex(np.arange(df['date'].min(), df['date'].max()+1))
.stack('key', dropna=False)
.loc[lambda x: x['size'].isna()]
.index
.to_frame(index=False))
输出:
date key
0 20181002 Hello
1 20181002 No
如何
重新塑造数据帧,使每行只有一个日期
下一步,重新索引数据帧以填充缺少的日期
重塑数据帧堆栈密钥,但保持NaN值
使用
isna
将数据帧筛选为仅缺少值使用to_frame 将索引转换为数据帧
更新@Cimbali在下面提到的地址日期问题
df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')
(df.pivot('date', 'key')
.reindex(pd.date_range(df['date'].min(), df['date'].max(), freq='D'))
.stack('key', dropna=False)
.loc[lambda x: x['size'].isna()]
.index
.to_frame(index=False))
输出:
0 key
0 2018-10-02 Hello
1 2018-10-02 No
如果我们将日期沿一个维度对齐,则可以更容易地查看(索引上的(公共值以及(列上的(填充位置。我们可以用pivot_table
来做到这一点。(这里的value
只是所有1
的占位符。(
>>> tab = df.assign(value=1).pivot_table(index='key', columns='date', values='value')
>>> tab
date 20181001 20181003 20181004
key
Hello 1 1 1
No 1 1 1
melt
允许我们进行相反的转换:
>>> tab.reset_index().melt(id_vars='key').drop(columns='value')
key date
0 Hello 20181001
1 No 20181001
2 Hello 20181003
3 No 20181003
4 Hello 20181004
5 No 20181004
因此,如果我们想要添加缺失日期的中间步骤,我们可能应该首先将它们转换为日期,并使用pd.date_range
:
>>> avail_dates = pd.to_datetime(tab.columns, format='%Y%m%d')
>>> avail_dates
DatetimeIndex(['2018-10-01', '2018-10-03', '2018-10-04'], dtype='datetime64[ns]', name='date', freq=None)
>>> all_dates = pd.date_range(avail_dates.min(), avail_dates.max(), freq='D')
>>> tab_filled = tab.reindex(all_dates.strftime('%Y%m%d').astype(int), axis='columns')
>>> tab_filled
20181001 20181002 20181003 20181004
key
Hello 1 NaN 1 1
No 1 NaN 1 1
最后只获取新的列,并执行我们的melt
技巧:
>>> missing = tab_filled.drop(columns=tab.columns).reset_index().melt('key').drop(columns=['value'])
>>> missing
key variable
0 Hello 20181002
1 No 20181002
这里有一个基于相同原理的较短变体,我们首先构建日期,然后构建一个合成数据帧,我们可以melt
:
>>> dates = pd.date_range(
... *pd.to_datetime(df['date'], format='%Y%m%d').agg(['min', 'max']), freq='D'
... ).strftime('%Y%m%d').astype(int)
>>> dates
Int64Index([20181001, 20181002, 20181003, 20181004], dtype='int64')
>>> pd.DataFrame(index=pd.Index(df['key'].unique(), name='key'),
... columns=dates.difference(df['date']))
... .reset_index().melt('key').drop(columns=['value'])
key variable
0 Hello 20181002
1 No 20181002