신용평가

python으로 구현한 간이 단변량분석 fineclassing

jaehwi0823 2019. 10. 18. 20:45

신용평가 등의 데이터 분석 시, fineclassing 단변량 분석을 진행한다. fineclassing을 통해 개별 항목의 분포를 확인하고, target과의 관계를 빠르게 살펴볼 수 있기 때문이다.

 

최근 분석에서 활용한 간이 fineclassing 코드는 다음과 같다. 급하게 만들어서 깔끔하지는 않지만 충분히 실무에서도 쓸 수 있을 것이다.

 

Args:

  • df: <pandas.DataFrame> 분석데이터
  • col: <String> 컬럼명
  • tgt: <String> target 컬럼명, 해당 컬럼은 0/1 binary 형식이어야 함
  • nbins: <Int> 숫자형 변수의 구간수, 숫자만큼 percentile을 계산해서 컬럼 분포를 확인

 

Return:

  • <pandas.DataFrame> 요약 결과 DataFrame을 반환

 

사용 코드:

from pandas.api.types import is_string_dtype
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

def FC(df, col, tgt, nbins):
    mydf = df[[col, tgt]].copy()
    
    if col == tgt:
        return

    elif is_string_dtype(df[col]):
        mydf = mydf.fillna("_Null")

        df_left = mydf[col].value_counts().to_frame()
        df_right = mydf.groupby(col)[tgt].sum()

        df_rslt = pd.concat([df_left, df_right], axis=1, sort=False)
        df_rslt['PCT'] = df_rslt[col]/len(df)*100
        df_rslt['BR'] = df_rslt[tgt]/df_rslt[col]*100

        return df_rslt

    else:
        fc_num = mydf[col].quantile([round(x/nbins, 2) for x in range(nbins)] + [1], interpolation='nearest').drop_duplicates().astype('float')
        sorted_values = sorted(set(fc_num.values))
        bins = np.insert(sorted_values, 0, -np.inf)
        labels =  fc_num.values

        cuts = pd.cut(mydf[col], bins=bins, labels=labels)
        df_left = cuts.value_counts()
        df_left_N = pd.Series({np.NaN: mydf[col].isnull().sum()}, name=col).to_frame()
        df_left_F = pd.concat([df_left_N, df_left.to_frame()], axis=0).sort_index()

        df_right = mydf.groupby(cuts)[tgt].sum()
        df_right_N = pd.Series({np.NaN: mydf.loc[mydf[col].isnull(), tgt].sum()}, name=tgt).to_frame()
        df_right_F = pd.concat([df_right_N, df_right.to_frame()], axis=0).sort_index()

        df_rslt = pd.concat([df_left_F, df_right_F], axis=1, sort=False)
        df_rslt['PCT'] = df_rslt[col]/len(mydf)*100
        df_rslt['BR'] = df_rslt[tgt]/df_rslt[col]*100
        df_rslt.index = df_rslt.index.astype(str)

    # graph
    fig, ax1 = plt.subplots()
    ax1.bar(df_rslt.index, df_rslt['PCT'])
    ax2 = ax1.twinx()
    ax2.plot(df_rslt.index, df_rslt['BR'], 'ro-')
    fig.tight_layout()
    plt.show()
    
    return df_rslt

 

사용예시:

  • FC(train_df, 'FEATURE1', 'TARGET', 20)

 

실제 사용예시

 

팁:

  • 이렇게 사용하면 한 눈에 전체 컬럼의 target rate를 한 눈에 볼 수 있다.
for column in mydf.columns:
	print(column)
    FC(mydf, column, 'TARGET', 20)

 

전체 컬럼 패턴 보기