Условные кумулятивные суммы в пандах - PullRequest
9 голосов
/ 14 июня 2019

Я бывший опытный пользователь Excel, раскаивающийся в своих грехах. Мне нужна помощь, чтобы воссоздать общий расчет для меня.

Я пытаюсь рассчитать эффективность кредитного портфеля. В числителе я рассчитываю совокупную сумму потерь. В знаменателе мне нужно первоначальное сальдо ссуд, включенных в совокупную сумму.

Я не могу понять, как создать условную групповую игру в Пандах для достижения этой цели. Это очень просто в Excel, поэтому я надеюсь, что я переосмысливаю это.

Я не смог найти много вопросов по StackOverflow, но это было ближе всего: условная кумулятивная сумма Python Pandas

Я не могу понять, что мои условия основаны на значениях в индексе и содержатся в столбцах

Ниже приведены мои данные:

| Loan    | Origination | Balance | NCO Date  | NCO | As of Date | Age     (Months) | NCO Age (Months) |
|---------|-------------|---------|-----------|-----|------------|--------------|------------------|
| Loan 1  | 1/31/2011   | 1000    | 1/31/2018 | 25  | 5/31/2019  | 100              | 84               |
| Loan 2  | 3/31/2011   | 2500    |           | 0   | 5/31/2019  | 98           |                  |
| Loan 3  | 5/31/2011   | 3000    | 1/31/2019 | 15  | 5/31/2019  | 96           | 92               |
| Loan 4  | 7/31/2011   | 2500    |           | 0   | 5/31/2019  | 94           |                  |
| Loan 5  | 9/30/2011   | 1500    | 3/31/2019 | 35  | 5/31/2019  | 92           | 90               |
| Loan 6  | 11/30/2011  | 2500    |           | 0   | 5/31/2019  | 90           |                  |
| Loan 7  | 1/31/2012   | 1000    | 5/31/2019 | 5   | 5/31/2019  | 88           | 88               |
| Loan 8  | 3/31/2012   | 2500    |           | 0   | 5/31/2019  | 86           |                  |
| Loan 9  | 5/31/2012   | 1000    |           | 0   | 5/31/2019  | 84           |                  |
| Loan 10 | 7/31/2012   | 1250    |           | 0   | 5/31/2019  | 82           |                  |

В Excel я бы вычислил эту сумму, используя следующие формулы:

Непогашенная линия баланса: =SUMIFS(Balance,Age (Months),Reference Age)

Cumulative NCO: =SUMIFS(NCO,Age (Months),>=Reference Age,NCO Age (Months),<=&Reference Age)

Данные:

| Reference Age       | 85    | 90    | 95   | 100  
|---------------------|-------|-------|------|------
| Outstanding Balance | 16500 | 13000 | 6500 | 1000 
| Cumulative NCO      | 25    | 60    | 40   | 25   

Цель здесь состоит в том, чтобы включить в выдающийся баланс вещи, которые достаточно взрослые, чтобы иметь возможность наблюдать за НКО. А НКО - это общая сумма, которая произошла до этого момента для этих непогашенных кредитов.

EDIT:

Я получил расчет таким образом. Но является ли это наиболее эффективным?

age_bins = list(np.arange(85, 101, 5))
final_df = pd.DataFrame()
df.fillna(value=0, inplace=True)
df["NCO Age (Months)"] = df["NCO Age (Months)"].astype(int)

for x in age_bins:

    age = x

    nco = df.loc[(df["Age (Months)"] >= x) & (df["NCO Age (Months)"] <= x), "NCO"].sum()

    bal = df.loc[(df["Age (Months)"] >= x), "Balance"].sum()

    temp_df = pd.DataFrame(
        data=[[age, nco, bal]],
        columns=["Age", "Cumulative NCO", "Outstanding Balance"],
        index=[age],
    )

    final_df = final_df.append(temp_df, sort=True)

Ответы [ 3 ]

1 голос
/ 14 июня 2019

Вы используете сложные условия в зависимости от переменных. Легко найти векторизованный способ для простых кумулятивных сумм, но я не могу представить себе хороший способ для Накопительного НКО.

Итак, я бы вернулся к пониманию Python:

data = [
    { 'Reference Age': ref,
      'Outstanding Balance': df.loc[df.iloc[:,6]>=ref,'Balance'].sum(),
      'Cumulative NCO': df.loc[(df.iloc[:,6]>=ref)&(df.iloc[:,7]<=ref),
                   'NCO'].sum() }
    for ref in [85, 90, 95, 100]]

result = pd.DataFrame(data).set_index('Reference Age').T

Производит:

Reference Age          85     90    95    100
Cumulative NCO          25     60    40    25
Outstanding Balance  16500  13000  6500  1000
0 голосов
/ 14 июня 2019

Не уверен, что я полностью следую точной логике, к которой вы стремитесь, но вы можете выполнить суфифы с помощью комбинации панд query и groupby.

Пример

import pandas as pd
import numpy as np

age = np.random.randint(85, 100, 50)
balance = np.random.randint(1000, 2500, 50)
nco = np.random.randint(85, 100, 50)

df = pd.DataFrame({'age': age, 'balance': balance, 'nco':nco})


df['reference_age'] = df['age'].apply(lambda x: 5 * round(float(x)/5))

outstanding_balance = (
   df
   .query('age >= reference_age')
   .groupby('reference_age')
   [['balance']]
   .sum()
   .rename(columns={'balance': 'Outstanding Balance'}
   )

cumulative_nco = (
   df
   .query('age < reference_age')
   .groupby('reference_age')
   [['nco']]
   .sum()
   .rename(columns={'nco': 'cumulative nco'})
   .cumsum()
   )


result = outstanding_balance.join(cumulative_sum).T

результат

reference_age            85       90       95
Outstanding Balance  2423.0  16350.0  13348.0
cumulative nco          NaN    645.0   1107.0
0 голосов
/ 14 июня 2019

Вы можете попытаться создать группы ссуд в данном возрастном диапазоне, используя pd.cut, а затем использовать groupby. Примерно так:

import pandas as pd

df = pd.DataFrame([[1, 2, 3, 4, 5], [7, 8, 9, 10, 11]], index=['age', 'value']).T
df['groups'] = pd.cut(df.age, [0, 1, 3, 5]) # define bins (0,1], (1,3], (3,5]
df.groupby('groups')['value'].sum()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...