Pandas 间隔数据(有效期从&有效期到)到月末重采样

Pandas interval data (valid from & valid to) to end of month resampling

我从数据库中提取了数据,其中一组用户的收入存储在 valid_from 和 valid_to 日期(每个用户可能有多个收入)。我想制作一个逐行数据集。在每一行上,我想显示每个用户分组的月末情况。

目前,我在索引上创建了一个包含所有可能月末的新数据框。然后我遍历这个索引并相应地填充数据框(通过从原始数据集中过滤)。

import pandas as pd
import numpy as np

test_dict = {'valid_from': [np.datetime64('2001-01-01'),np.datetime64('2001-01-15'),np.datetime64('2001-06-20')],\
             'valid_to': [np.datetime64('2001-12-31'),np.datetime64('2001-04-15'),np.datetime64('2001-11-10')],\
             'user' : ['a','b','a'],\
             'income': [200,300,400]}
interval_data = pd.DataFrame(test_dict, columns=['valid_from','valid_to','user','income'])
end_of_month = pd.date_range(start = interval_data.valid_from.min(), end=interval_data.valid_to.max(), freq='M')

dfs = []
for x in end_of_month:
    fltr = (x >= interval_data.valid_from) & (x <= interval_data.valid_to)
    df = interval_data.loc[fltr, :].copy()
    df['date'] = x
    dfs.append(df)

df = pd.concat(dfs)
group = df.loc[:,['date','user','income']].groupby(['date','user']).sum()

print(interval_data)
print(group)

但是我想有一种更有效的方法可以使用 Pandas 中存在的各种时间和日期函数来执行上述逻辑。

有什么建议吗?

IIUC:

interval_data.groupby(level=0,group_keys=False, as_index=False)\
             .apply(lambda x: pd.DataFrame({'user':x.user.values,'income':x.income.values},
                                           index=pd.date_range(x.valid_from.values[0],
                                                               x.valid_to.values[0],
                                                               freq='M')))\
             .set_index('user',append=True).sort_index().sum(level=[0,1])

输出:

                 income
           user        
2001-01-31 a        200
           b        300
2001-02-28 a        200
           b        300
2001-03-31 a        200
           b        300
2001-04-30 a        200
2001-05-31 a        200
2001-06-30 a        600
2001-07-31 a        600
2001-08-31 a        600
2001-09-30 a        600
2001-10-31 a        600
2001-11-30 a        200
2001-12-31 a        200