条件重译 - 熊猫

时间:2018-01-25 22:52:19

标签: python pandas

我有一种情况,我想根据合约开始日期,结束日期和总支出来计算每日支出。下一步是按月汇总每日支出金额。这很容易,我将在稍后完成。但是,还有另一个日期(inv date);如果startinv date之前,那么inv date之前的所有每日金额应该加总并包含在与inv date相同的时间段内。

首先,简单部分

df = pd.DataFrame({'start': ['1/1/2018'], 
               'end': ['3/15/2018'], 
               'inv date': ['2/1/2018'],
               'spend': [400]})


         start        end   inv date    spend
0     1/1/2018  3/15/2018   2/1/2018      400

创建合约的日期范围

prd = pd.period_range(df.loc[0, 'start'], df.loc[0, 'end'], freq='D')
prd = pd.Series(1, prd) # empty series to get the number of days in the monthly period
prd = prd.resample('M').size() * (df.loc[0, 'spend'] / prd.resample('M').size().sum())

这给了我以下系列:按月分配的总支出,根据当月的天数...到目前为止,非常好。

prd

2018-01    167.567568
2018-02    151.351351
2018-03     81.081081
Freq: M, dtype: float64 

困难的部分(对我来说)

正如我上面提到的,基于inv date,系列实际上应该是这样的:

2018-01             0 
2018-02    318.918919
2018-03     81.081081
Freq: M, dtype: float64

因为inv date是在start日期之后,所以我不想在inv date之后添加它。 FYI :318 = 167 + 151(即上述2/2018的总数)。

resample这可能吗?如果没有,那么最有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

从“简单部分”部分末尾的dfprd开始:

# Get the inv date as a pandas Timestamp
invdate = pd.to_datetime(df['inv date'])[0]
oneday = pd.offsets.Day(1)
# Pandas slicing includes BOTH endpoints, so we need this one-day 
# offset to get all values strictly before the inv date
prd.loc[invdate] = prd[invdate] + prd[:invdate - oneday].sum()
prd.loc[:invdate - oneday] = 0

# output
2018-01      0.000000
2018-02    318.918919
2018-03     81.081081
Freq: M, dtype: float64