Python 基于列日期在数据框中为每个月添加行

Python 基于列日期在数据框中为每个月添加行,python,pandas,datetime,calendar,Python,Pandas,Datetime,Calendar,我正在处理我需要为不同月份推断的财务数据。这是我的数据框: invoice_id,date_from,date_to 30492,2019-02-04,2019-09-18 我想在date\u from和date\u to之间的不同月份将其分解。因此,我需要为每个月添加行,从月份开始日期到结束日期。最终输出应如下所示: invoice_id,date_from,date_to 30492,2019-02-04,2019-02-28 30492,2019-03-01,2019-03-31 304

我正在处理我需要为不同月份推断的财务数据。这是我的数据框:

invoice_id,date_from,date_to
30492,2019-02-04,2019-09-18
我想在date\u fromdate\u to之间的不同月份将其分解。因此,我需要为每个月添加行,从月份开始日期到结束日期。最终输出应如下所示:

invoice_id,date_from,date_to
30492,2019-02-04,2019-02-28
30492,2019-03-01,2019-03-31
30492,2019-04-01,2019-04-30
30492,2019-05-01,2019-05-31
30492,2019-06-01,2019-06-30
30492,2019-07-01,2019-07-31
30492,2019-08-01,2019-08-30
30492,2019-09-01,2019-09-18

还需要考虑闰年的情况。在pandas datetime包中是否有任何本机方法可用于实现所需的输出

您可以使用带有开始日期和结束日期的
pandas.date\u range
,以及作为月初的
freq='MS'
和作为月底的
freq='M'

x = pd.date_range(start=df.iloc[0]['date_from'], end=df.iloc[0]['date_to'], freq='MS')
y = pd.date_range(start=df.iloc[0]['date_from'], end=df.iloc[0]['date_to'], freq='M')

df_new = pd.DataFrame({'date_from':x,
                       'date_to':y})

df_new['invoice_id'] = df.iloc[0]['invoice_id']

print(df_new)
   date_from    date_to  invoice_id
0 2019-03-01 2019-02-28       30492
1 2019-04-01 2019-03-31       30492
2 2019-05-01 2019-04-30       30492
3 2019-06-01 2019-05-31       30492
4 2019-07-01 2019-06-30       30492
5 2019-08-01 2019-07-31       30492
6 2019-09-01 2019-08-31       30492
使用:


另一种方法是,使用日期时间索引的
重采样方法:

# melt, so we have start and end dates in 1 column
df = pd.melt(df, id_vars='invoice_id')
# now set the date column as index
df.set_index(inplace=True, keys='value')
# resample to daily level
df = df.resample('D').ffill().reset_index()
# get the yr-month value of each daily row
df['yr_month'] = df['value'].dt.strftime("%Y-%m")

# Now group by month and take min/max day values
output = (df.groupby(['invoice_id', 'yr_month'])['value']
          .agg({'date_from': 'min', 'date_to': 'max'})
          .reset_index()
          .drop(labels='yr_month', axis=1))

print(output)

   invoice_id  date_from    date_to
0       30492 2019-02-04 2019-02-28
1       30492 2019-03-01 2019-03-31
2       30492 2019-04-01 2019-04-30
3       30492 2019-05-01 2019-05-31
4       30492 2019-06-01 2019-06-30
5       30492 2019-07-01 2019-07-31
6       30492 2019-08-01 2019-08-31
7       30492 2019-09-01 2019-09-18
# melt, so we have start and end dates in 1 column
df = pd.melt(df, id_vars='invoice_id')
# now set the date column as index
df.set_index(inplace=True, keys='value')
# resample to daily level
df = df.resample('D').ffill().reset_index()
# get the yr-month value of each daily row
df['yr_month'] = df['value'].dt.strftime("%Y-%m")

# Now group by month and take min/max day values
output = (df.groupby(['invoice_id', 'yr_month'])['value']
          .agg({'date_from': 'min', 'date_to': 'max'})
          .reset_index()
          .drop(labels='yr_month', axis=1))

print(output)

   invoice_id  date_from    date_to
0       30492 2019-02-04 2019-02-28
1       30492 2019-03-01 2019-03-31
2       30492 2019-04-01 2019-04-30
3       30492 2019-05-01 2019-05-31
4       30492 2019-06-01 2019-06-30
5       30492 2019-07-01 2019-07-31
6       30492 2019-08-01 2019-08-31
7       30492 2019-09-01 2019-09-18