python把文字矢量化_python pandas:尝试使用date_range对函数进行矢量化

我最终想出了这个解决方案(很大程度上受到了@jezrael对这个 post的回答).可能不是最节省内存的解决方案,但这对我来说不是主要问题,执行时间就是问题所在!

from pandas.tseries.offsets import MonthBegin

df['ID'] = range(len(df))

df['TOTAL_DAYS'] = (df.STOP_DATE - df.START_DATE).dt.days + 1

df

>>> AMOUNT KEY START_DATE STOP_DATE ID TOTAL_DAYS

0 5 A 2018-01-05 2018-01-22 0 18

1 3 B 2018-01-04 2018-03-10 1 66

2 11 C 2018-01-01 2018-01-31 2 31

3 14 A 2018-01-23 2018-02-15 3 24

4 7 A 2018-02-01 2018-04-01 4 60

5 9 B 2018-03-11 2018-07-21 5 133

final = (df[['ID', 'START_DATE', 'STOP_DATE']].set_index('ID').stack()

.reset_index(level=-1, drop=True)

.rename('DATE_AFTER')

.to_frame())

final = final.groupby('ID').apply(

lambda x: x.set_index('DATE_AFTER').resample('M').asfreq()).reset_index()

final = final.merge(df[['ID', 'KEY', 'AMOUNT', 'TOTAL_DAYS']], how='left', on=['ID'])

final['PERIOD'] = final.DATE_AFTER.dt.to_period('M')

final['DATE_BEFORE'] = final.DATE_AFTER - MonthBegin()

在这一点上,final看起来像这样:

final

>>> ID DATE_AFTER KEY AMOUNT TOTAL_DAYS PERIOD DATE_BEFORE

0 0 2018-01-31 A 5 18 2018-01 2018-01-01

1 1 2018-01-31 B 3 66 2018-01 2018-01-01

2 1 2018-02-28 B 3 66 2018-02 2018-02-01

3 1 2018-03-31 B 3 66 2018-03 2018-03-01

4 2 2018-01-31 C 11 31 2018-01 2018-01-01

5 3 2018-01-31 A 14 24 2018-01 2018-01-01

6 3 2018-02-28 A 14 24 2018-02 2018-02-01

7 4 2018-02-28 A 7 60 2018-02 2018-02-01

8 4 2018-03-31 A 7 60 2018-03 2018-03-01

9 4 2018-04-30 A 7 60 2018-04 2018-04-01

10 5 2018-03-31 B 9 133 2018-03 2018-03-01

11 5 2018-04-30 B 9 133 2018-04 2018-04-01

12 5 2018-05-31 B 9 133 2018-05 2018-05-01

13 5 2018-06-30 B 9 133 2018-06 2018-06-01

14 5 2018-07-31 B 9 133 2018-07 2018-07-01

然后我们将初始df合并两次(开始和月末):

final = pd.merge(

final,

df[['ID', 'STOP_DATE']].assign(PERIOD = df.STOP_DATE.dt.to_period('M')),

how='left', on=['ID', 'PERIOD'])

final = pd.merge(

final,

df[['ID', 'START_DATE']].assign(PERIOD = df.START_DATE.dt.to_period('M')),

how='left', on=['ID', 'PERIOD'])

final['STOP_DATE'] = final.STOP_DATE.combine_first(final.DATE_AFTER)

final['START_DATE'] = final.START_DATE.combine_first(final.DATE_BEFORE)

final['DAYS'] = (final.STOP_DATE- final.START_DATE).dt.days + 1

final = final.drop(columns=['ID', 'DATE_AFTER', 'DATE_BEFORE'])

final.AMOUNT *= final.DAYS/final.TOTAL_DAYS

final = final.groupby(['KEY', 'PERIOD']).agg({'AMOUNT': sum, 'DAYS': sum})

有了预期的结果:

AMOUNT DAYS

KEY PERIOD

A 2018-01 10.250000 27

2018-02 12.016667 43

2018-03 3.616667 31

2018-04 0.116667 1

B 2018-01 1.272727 28

2018-02 1.272727 28

2018-03 1.875598 31

2018-04 2.030075 30

2018-05 2.097744 31

2018-06 2.030075 30

2018-07 1.421053 21

C 2018-01 11.000000 31

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值