Programming

dpd

import numpy as np
import pandas as pd

id_cols = ['dealid', 'data_given']
month_cols = [c for c in df.columns if c not in id_cols]

# "03/25" or "03/2025" -> Period('2025-03', 'M')
def to_period(c):
    m, y = c.split('/')
    y = int(y)
    y = y + 2000 if y < 100 else y
    return pd.Period(year=y, month=int(m), freq='M')

periods = pd.Series({c: to_period(c) for c in month_cols}).sort_values()
sorted_cols = periods.index.tolist()
pos = {p: i for i, p in enumerate(periods.values)}   # period -> column index

# 1) first_return
dg = pd.to_datetime(df['data_given'], dayfirst=True)
given_m = dg.dt.to_period('M')
df['first_return'] = (given_m + 2).dt.to_timestamp()

# 2) starting column for dpd_0  (= first_return month - 1)
start = given_m.add(1).map(pos).astype('float')   # NaN if that month has no column

# 3) shift each row so dpd_0 lands on its start column
vals = df[sorted_cols].to_numpy(dtype='float64')
n = vals.shape[1]
padded = np.hstack([vals, np.full((len(df), 1), np.nan)])   # last col = NaN sink

idx = start.to_numpy()[:, None] + np.arange(n)[None, :]
ok = np.isfinite(idx) & (idx >= 0) & (idx < n)
idx = np.where(ok, idx, n).astype(int)

out = np.take_along_axis(padded, idx, axis=1)
dpd = pd.DataFrame(out, index=df.index,
                   columns=[f'dpd_{i}' for i in range(n)])
dpd = dpd.dropna(axis=1, how='all')          # trim unused tail columns

df = pd.concat([df, dpd], axis=1)
Helpful? Dislike 0 Log in to react