python如何找到从2019年12月开始的每个月的天数,然后在两个日期列之间转发

问题描述 投票:2回答:2

我有两个日期列'StartDate'和'EndDate'。我想查找从2019年12月起的两个日期之间每个月的天数,并向前忽略2019年之前的任何几个月进行计算。每行的StartDate和EndDate可以跨2年,月份重叠,并且Date列也可以为空。

样本数据:

df = {'Id': ['1','2','3','4','5','6','7', '8'],
      'Item': ['A','B','C','D','E','F','G', 'H'],
        'StartDate': ['2019-12-10', '2019-12-01', '2019-10-01', '2020-01-01', '2019-03-01','2019-03-01','2019-10-01', ''],
        'EndDate': ['2020-02-21' ,'2020-01-01','2020-08-31','2020-01-30','2019-12-31','2019-12-31','2020-08-31', '']
        }
df = pd.DataFrame(df,columns= ['Id', 'Item','StartDate','EndDate'])

预期O / P:

“

下面的解决方案部分起作用。

df['StartDate'] = pd.to_datetime(df['StartDate'])
df['EndDate'] = pd.to_datetime(df['EndDate'])

def days_of_month(x):
    s = pd.date_range(*x, freq='D').to_series()
    return s.resample('M').count().rename(lambda x: x.month)

df1 = df[['StartDate', 'EndDate']].apply(days_of_month, axis=1).fillna(0)

df_final = df[['StartDate', 'EndDate']].join([df['StartDate'].dt.year.rename('Year'), df1])
python pandas numpy dataframe
2个回答
0
投票

尝试一下:

df.join(df.dropna(axis=0,how='any')
         .apply(lambda x: pd.date_range(x['StartDate'],x['EndDate'], freq='D')
         .to_frame().resample('M').count().loc['2019-12-01':].unstack(), axis=1)[0].fillna(0))

输出:

 Id Item  StartDate    EndDate  2019-12-31 00:00:00  2020-01-31 00:00:00  2020-02-29 00:00:00  2020-03-31 00:00:00  2020-04-30 00:00:00  2020-05-31 00:00:00  2020-06-30 00:00:00  2020-07-31 00:00:00  2020-08-31 00:00:00
0  1    A 2019-12-10 2020-02-21                 22.0                 31.0                 21.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0
1  2    B 2019-12-01 2020-01-01                 31.0                  1.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0
2  3    C 2019-10-01 2020-08-31                 31.0                 31.0                 29.0                 31.0                 30.0                 31.0                 30.0                 31.0                 31.0
3  4    D 2020-01-01 2020-01-30                  0.0                 30.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0
4  5    E 2019-03-01 2019-12-31                 31.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0
5  6    F 2019-03-01 2019-12-31                 31.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0                  0.0
6  7    G 2019-10-01 2020-08-31                 31.0                 31.0                 29.0                 31.0                 30.0                 31.0                 30.0                 31.0                 31.0
7  8    H        NaT        NaT                  NaN                  NaN                  NaN                  NaN                  NaN                  NaN                  NaN                  NaN                  NaN

0
投票

我们将创建两个大的DataFrame,一个在每个月的开始,另一个在每个月的结束。然后,我们将它们相应地裁剪,这给我们提供了一个简单的减法。由于您要包含结束日期,因此我们需要添加1天,然后我们清除所有负日期(应为0)。

import pandas as pd

df_s = pd.DataFrame([pd.date_range('2019-12-01', '2020-12-01', freq='MS').to_numpy()],
                     index=df.index)
df_e = (pd.DataFrame([pd.date_range('2019-12-01', '2020-12-01', freq='MS').to_numpy()], 
                     index=df.index)
         + pd.offsets.MonthEnd(1))

df_s = df_s.clip(lower=pd.to_datetime(df.StartDate), axis=0)
df_e = df_e.clip(upper=pd.to_datetime(df.EndDate), axis=0)

res = ((df_e - df_s) + pd.to_timedelta(1, 'd')).clip(lower=pd.to_timedelta(0, 'd'))
res.columns = pd.period_range(start='2019-12', end='2020-12', freq='M')

# So int 
for col in res.columns:
    res[col] = res[col].dt.days

df = pd.concat([df, res], axis=1)

  Id Item   StartDate     EndDate  2019-12  2020-01  2020-02  2020-03  2020-04  2020-05  2020-06  2020-07  2020-08  2020-09  2020-10  2020-11  2020-12
0  1    A  2019-12-10  2020-02-21     22.0     31.0     21.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0
1  2    B  2019-12-01  2020-01-31     31.0     31.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0
2  3    C  2019-10-01  2020-08-31     31.0     31.0     29.0     31.0     30.0     31.0     30.0     31.0     31.0      0.0      0.0      0.0      0.0
3  4    D  2020-01-01  2020-01-30      0.0     30.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0
4  5    E  2019-03-01  2019-12-31     31.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0
5  6    F  2019-03-01  2019-12-31     31.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0      0.0
6  7    G  2019-10-01  2020-08-31     31.0     31.0     29.0     31.0     30.0     31.0     30.0     31.0     31.0      0.0      0.0      0.0      0.0
7  8    H                              NaN      NaN      NaN      NaN      NaN      NaN      NaN      NaN      NaN      NaN      NaN      NaN      NaN
© www.soinside.com 2019 - 2024. All rights reserved.