본문 바로가기
DB 공부하기

230411_DB복습

by 보랏 2023. 4. 11.

안녕하세요. 보랏입니다.

 

오늘은 머신러닝 금융 데이터 활용 데이터 분석을 진행하였으며

Django를 활용한 웹 페이지를 구축하였습니다.

 

복습 시작하겠습니다. 

 

1. 머신러닝 - 금융 데이터 활용 디폴트 찾기 (출처 : 금융 파이썬 쿡북)

  • 사용되는 데이터 셋은 2005년 10월 대만 은행에서 수집한 것으로 '과거 상환 내역과 함께 고객에 대한 몇 가지 기본정보 (성별, 연령 교육 수준)을 사용해 디폴트 가능성이 높은 사람을 예측
  • 6개월의 상환내역 (2005년 4월 ~9월)을 사용해 고객이 2005년에 10월에 디폴트를 할지 말지 여부 예측

 

데이터 읽기 및 유형 관리 (메모리 최적화 가능)

  • separator 문자는 무엇인가?
  • 별도 처리해야 하는 특수 문자가 존재하는가?
  • 누락된 값(결측치)이 있는가? 그렇다면 어떻게 처리해야하나?
  • 파일에 있는 변수 유형(float, integer, string)은 무엇인가?
df = pd.read_csv('credit_card_default.csv', index_col=0, na_values='')
print(f'The DataFrame has {len(df)} rows and {df.shape[1]} columns.')
df.head()

  • Target(y값) 추출
X = df.copy()
y = X.pop('default_payment_next_month')

X.columns

  • 메모리 사용량 확인하기 
    • type이 object인 컬럼을 대상으로 category(범주형) 데이터 타입으로 변경하여 메모리 절약 가능
# 실제로 메모리를 얼마나 사용중인가 확인하는 함수
def get_df_memory_usage(df, top_columns=5):
    '''
    Function for quick analysis of a pandas DataFrame's memory usage.
    It prints the top `top_columns` columns in terms of memory usage 
    and the total usage of the DataFrame.
    
    Parameters
    ------------
    df : pd.DataFrame
        DataFrame to be inspected
    top_columns : int
        Number of top columns (in terms of memory used) to display
    '''
    print('Memory usage ----')
    memory_per_column = df.memory_usage(deep=True) / 1024 ** 2
    print(f'Top {top_columns} columns by memory (MB):')
    print(memory_per_column.sort_values(ascending=False) \
                           .head(top_columns))
    print(f'Total size: {memory_per_column.sum():.4f} MB')
    
    
get_df_memory_usage(df, 5)

df_cat = df.copy()
object_columns = df_cat.select_dtypes(include='object').columns
df_cat[object_columns] = df_cat[object_columns].astype('category')


get_df_memory_usage(df_cat, 5)

 

탐색적 데이터 분석 (Exploratory Data Analysis)

  • 실제로 어떤 종류의 데이터를 갖고 있으며 다른 유형을 어떻게 다뤄야 하는가?
  • 변수의 분포는 무엇인가?
    • 데이터에 특이값이 있는가? 어떻게 처리할 수 있는가?
    • 변환이 필요한가? 예를 들어, 일부 모델은 정규 분포 변수와 더 잘 작동하거나 로그 변환과 같은 기술을 사용할 수 있다.
    • 분포는 그룹마다 다른가?(예: 성별 또는 교육 수준)
  • 데이터가 누락된 경우가 있는가?
  • 얼마나 빈번하고 어떤 변수에 있는가?
  • 일부 변수 간에 선형(상관) 관계가 있는가?
  • 기존 변수 집합을 사용해 새 특징을 생성할 수 있는가?
    • 타임 스탬프에서 시간/분, 날짜에서 요일 등을 예로 들수 있다
  • 분석과 관련이 없기 때문에 제거할 수 있는 변수가 있는가?
    • 무작위로 생성된 고객 식별자를 예로 들 수 있다.

 

수치형 데이터 기술 통계값

  • describe()를 사용하여 수치형 데이터의 개수, 평균, 최소/최대 및 사분위수와 같은 요약 통계 출력
  • 이러한 지표를 검사해 특정 특징의 값 범위 또는 분포가 왜곡됐는지 평균값과 중앙값의 차이를 확인해 추정 가능.
  • 음수나 매우 작은 연령 등 가능한 범위를 벗어난 값을 쉽게 발견 가능
df.describe().transpose().round(2)

범주형 변수에 대한 기술 통계량 

  • include 매개변수에 'object'인수를 추가하면 범주 특징을 개별적으로 출력 가능
df.describe(include='object').transpose()

데이터 시각화

  • 나이 분포를 도식화하여 추가적으로 성별로 분할하기
  • 단일 특징의 분포를 검사하는 보편적인 방법중 하나
  • hist = True를 사용하면 히스토그램을 만들수 있음
import matplotlib.pyplot as plt
import warnings

plt.style.use('seaborn')
plt.rcParams['figure.figsize'] = [8, 4.5]
plt.rcParams['figure.dpi'] = 300
warnings.simplefilter(action='ignore', category=FutureWarning)


fig, ax = plt.subplots()
sns.distplot(df.loc[df.sex=='Male', 'age'].dropna(), 
             hist=False, color='green', 
             kde_kws={'shade': True},
             ax=ax, label='Male')
sns.distplot(df.loc[df.sex=='Female', 'age'].dropna(), 
             hist=False, color='blue', 
             kde_kws={'shade': True},
             ax=ax, label='Female')
ax.set_title('Distribution of age')
ax.legend(title='Gender:')

plt.tight_layout()
# plt.savefig('images/ch8_im5.png')
plt.show()

선택된 변수에 대해 pairplot을 도식화

  • 대각선은 일변량 히스토그램을 나타내고, 비대각은 두 변수의 산점도를 나타낸다.
  • 이 방법으로 두 변수 간에 관계가 있는지 확인할 수 있다.
pair_plot = sns.pairplot(df[['age', 'limit_bal', 'previous_payment_sep']])
pair_plot.fig.suptitle('Pairplot of selected variables', y=1.05)

plt.tight_layout()
# plt.savefig('images/ch8_im6.png', bbox_inches='tight')
plt.show()

 

상관관계 히트맵(heatmap)을 그리는 함수를 정의하고 실행

def plot_correlation_matrix(corr_mat):
    '''
    Function for plotting the correlation heatmap. It masks the irrelevant fields.
    
    Parameters
    ----------
    corr_mat : pd.DataFrame
        Correlation matrix of the features.
    '''
    
    # temporarily change style
    sns.set(style='white')
    # mask the upper triangle
    mask = np.zeros_like(corr_mat, dtype=bool)
    mask[np.triu_indices_from(mask)] = True
    # set up the matplotlib figure
    fig, ax = plt.subplots()
    # set up custom diverging colormap
    cmap = sns.diverging_palette(240, 10, n=9, as_cmap=True)
    # plot the heatmap
    sns.heatmap(corr_mat, mask=mask, cmap=cmap, vmax=.3, center=0,
                square=True, linewidths=.5, 
                cbar_kws={'shrink': .5}, ax=ax)
    ax.set_title('Correlation Matrix', fontsize=16)
    # change back to darkgrid style
    sns.set(style='darkgrid')
    
    
corr_mat = df.select_dtypes(include='number').corr()    
plot_correlation_matrix(corr_mat)

plt.tight_layout()
#plt.savefig('images/ch8_im7.png')
plt.show()

df.select_dtypes(include='number').corr()[['default_payment_next_month']]

 

  • 이렇게 EDA를 따로 시행하는 방법도 있지만 EDA를 한 번에 해주는 라이브러리가 pandas_profiling 라이브러리를 사용하여 단 한줄의 코드로 HTML보고서 형식으로 데이터셋에 대한 포괄적인 요약을 생성함
pip install pandas_profiling
import pandas_profiling
df.profile_report()

 

 


 

2. Django 웹 페이지 구축 및 CSS활용

  • 어제 만든 Answer, Question 클래스(DB)를 활용하여 홈페이지 제작을 추가로 진행하였습니다. 
  • admin.py에 Question 클래스 (DB) 등록 

  • views.py에 Question의 objects 컬럼을 불러오는 함수 생성
    • q_list 는 Qusetion의 objects컬럼을 create_date를 내림차순으로 정렬
    • pybo폴더에 question_list.html 파일에서 question_list라는 key값을 입력하여 q_list 값을 호출
    • pybo폴더 아래 question_list.html 파일 생성 후 question_list를 불러오는 함수 생성 필요 

  • 이 때, html 파일은 무수히 많아질 수가 있어 같은 pybo폴더에서 관리하기 보다 새롭게 폴더를 만들어 전용 템플릿(html) 관리하는 것이 좋음
    • 상위폴더에 templates라는 폴더를 생성하고 그 안에 새롭게 pybo라는 폴더 생성
    • setting.py -> base.py 파일 접속 후 TEMPLATES 에서 DIRS 를 [BASE_DIR / 'templates'] 로 수정 후 저장

 

  • templates --> pybo폴더 아래 question_list.html 파일 생성 후 아래 코드 입력
{% if question_list %}  ## question_List 가 있다면
    <ul>
    {% for question in question_list %}  # question값(views.py의 index함수의 q_list값을 반복하여)
        <li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li> # 주소값을 pybo/question_id 값으로 하고/question.subject값을 불러오기 
    {% endfor %}
    </ul>
{% else %}
    <p>질문이 없습니다.</p> #question_list 가 없으면 질문이 없습니다. 출력
{% endif %}

 

  • 이제 질문을 입력하였으니 그에 대한 대답을 응답할 수 있는 페이지를 생성하려고 합니다. 
  • views.py에서 대답 시 응답하는 함수를 생성
    • request 값과 question에 FK로 응답할 수 있도록 입력값을 'request', 'question_id'를 입력 변수로 받기
    • get_object_or_404 라이브러리를 활용하여 유효 값일 시 object를 출력하고 아닐 시 404포트 페이지를 출력

  • detail함수를 호출할 수 있는 html파일 생성
    • question.subject를 <h1>로 question.content를 <div> 로 지정하여 html파일 생성

  • 현재 question_list.html 에서 url을 호출하는 링크명이 <a href="/pybo/{{ question.id }}/"> 으로 되어 있는데 이러한 url링크는 수정될 가능성이 있어 향후 사용한 url들을 일일히 찾아가며 수정해야 하는 리스크가 발생함--> 이러한 문제점을 해결하기 위해서는 해당 url에 대한 실제 링크 대신 링크의 주소를 1:1로 매칭 시켜주는 별칭 생성 필요

  • pybo / urls.py에 name 값 지정 필요
    • views.detail 함수에 name 을 'detail'로 지정
  • question_detail.html 파일에서 아래코드 입력
    • 질문 상세 템플릿에 답변을 저장할 수 있는 폼(form)추가
    • 답변의 내용을 입력할 수 있는 텍스트창(textarea)과 답변을 저장할 수 있는 '답변등록'버튼 추가
    • 답변 저장을 위한 url은 form태그의 action속성에 {% url 'pybo:answer_create' question.id%} 로 지정
    • form 태그 밑에 있는 {% csrf_token %} 은 보안에 관련된 항목으로 form으로 전송한 데이터가 실제 웹 페이지에서 작성한 데이터인지를 판단하는 가늠하는 역할 진행 (ex : 해커가 서버에서 발행한 csrf_token값과 해커가 보낸 token값이 불일치 할 시 블록킹)

 

  • question_detail.html 파일에 answer_create <form>을 생성하였으니 이제 이를 접속할 수 있는 url.py과 views.py 생성 필요

  • answer_create 별칭에 해당하는 url매칭 규칙을 등록하여 www.localhost:8000/pybo/answer/create/1/ 과 같이 입력 시 views.answer_create 함수를 호출

  • pk는 question_id를 넘겨받고, request는 form 의  textarea에 입력된 답변 내용을 넘겨받음, 여기서 해당 텍스트 내용만을 추출하기 위한 코드가 request.POST.get('content')
  • Question모델을 통해 Answer 모델 데이터를 생성하기 위해 question.answer_set.create 라는 ORM 생성
  • redirect('pybo : detail', question_id = question_id)를 통해 question_detail.html파일로 이동

  • 이제 부트스트랩 CSS파일을 활용해서 question_list.html 파일을 꾸미도록 하겠습니다. 
  • pybo 폴더 밑에 static이라는 폴더를 생성한 뒤 강사님께서 제공해주신 부트스트랩 css파일을 저장하였습니다.

  • settings.py에 base.py에 접속하여 아래 코드로 내용 수정
STATICFILES_DIRS = [
    BASE_DIR / 'static',
]
  • 이제 question_list.html을 아래 코드로 변경하였습니다.
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'bootstrap.min.css' %}">


<div class="container my-3">
    <table class="table">
        <thead>
        <tr class="table-dark">
            <th>번호</th>
            <th>제목</th>
            <th>작성일시</th>
        </tr>
        </thead>
        <tbody>
        {% if question_list %}
        {% for question in question_list %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>
                <a href="{% url 'pybo:detail' question.id %}">{{ question.subject }}</a>
            </td>
            <td>{{ question.create_date }}</td>
        </tr>
        {% endfor %}
        {% else %}
        <tr>
            <td colspan="3">질문이 없습니다.</td>
        </tr>
        {% endif %}
        </tbody>
    </table>
</div>

 

 

이렇게 오늘 복습도 마무리 하겠습니다. 

 

감사합니다.

'DB 공부하기' 카테고리의 다른 글

230418_DB복습  (0) 2023.04.18
230417_DB복습  (0) 2023.04.17
230410_DB복습  (0) 2023.04.10
230406_DB복습  (0) 2023.04.07
230405_DB복습  (0) 2023.04.05