본문 바로가기

Data Science/Data Preprocessing

[03. Feature Engineering] 005. Dummy

728x90

범주형 변수를 모델링을 하기 위해서는 더미변수를 만들어 모델링한다. 문자 그대로는 모델링 할 수 없기 때문이다.

 

from bs4 import BeautifulSoup
import pandas as pd
import requests
from io import BytesIO
from zipfile import ZipFile
import json

def get_company_code(api_key):
    url = 'https://opendart.fss.or.kr/api/corpCode.xml?crtfc_key=%s' % api_key
    response = requests.get(url)
    zip_file = ZipFile(BytesIO(response.content))
    files = zip_file.namelist()
    soup = ''

    with zip_file.open(files[0]) as csvfile:
        soup = BeautifulSoup(csvfile.read(), 'lxml')
        soup = soup.findAll('list')

    data = []
    for company in soup:
        data.append({
            'corp_code': company.corp_code.text,
            'corp_name': company.corp_name.text,
            'stock_code': company.stock_code.text,
            'modify_date': company.modify_date.text
        })

    return pd.DataFrame(data)

def get_multi_account(api_key, code, year, report_code):
    fullUrl = 'https://opendart.fss.or.kr/api/fnlttMultiAcnt.json?crtfc_key=%s&corp_code=%s&' \
              'bsns_year=%s&reprt_code=%s' % (api_key, code, year, report_code)

    response = requests.get(fullUrl, headers={'User-Agent': 'Mozilla/5.0'})
    result = response.text
    result = json.loads(result)

    if result['status'] == '000':
        data = pd.DataFrame(result['list'])

        return data

if __name__ == '__main__':
    api_key = '*'
    company_code = get_company_code(api_key)
    cmpy = ['005930', '005380', '000660','035720', '035420', '093050', '051910', '207940', '051900']
    code = ','.join(company_code[company_code['stock_code'].isin(cmpy)]['corp_code'].tolist())
    year = '2020'
    report_code = '11011'

    multi_account = get_multi_account(api_key, code, year, report_code)
    multi_account = multi_account[['stock_code', 'fs_nm', 'account_nm', 'thstrm_dt', 'thstrm_amount']]
    multi_account = multi_account[(multi_account['fs_nm']=='연결재무제표') & (multi_account['account_nm']=='당기순이익')]
    multi_account['thstrm_amount'] = multi_account['thstrm_amount'].str.replace(',', '').astype(float) / 100000000

    multi_account = multi_account.merge(company_code[['stock_code', 'corp_name']], how='left', on='stock_code')
    multi_account['thstrm_dt'] = multi_account['thstrm_dt'].str.split('~', expand=True)[1].str.strip().str.replace('.', '-')

    cap = pd.DataFrame([
        {'stock_code': '005930', 'cap': 4835524},
        {'stock_code': '005380', 'cap': 511735},
        {'stock_code': '000660', 'cap': 910003},
        {'stock_code': '035720', 'cap': 701409},
        {'stock_code': '035420', 'cap': 675944},
        {'stock_code': '093050', 'cap': 5980},
        {'stock_code': '051910', 'cap': 592270},
        {'stock_code': '207940', 'cap': 559756},
        {'stock_code': '051900', 'cap': 274412},
    ])

    multi_account = multi_account.merge(cap, how='left', on='stock_code')
    multi_account['PER'] = multi_account['cap'] / multi_account['thstrm_amount']
    multi_account['1/PER'] = 1 / multi_account['PER']
    multi_account['bin'] = pd.cut(x=multi_account['1/PER'], bins=[multi_account['1/PER'].quantile(0), multi_account['1/PER'].quantile(0.33), multi_account['1/PER'].quantile(0.66), multi_account['1/PER'].quantile(1)], labels=['고PER','평균PER','저PER'], include_lowest=True)

    print(pd.concat([multi_account[['stock_code', 'corp_name', '1/PER', 'bin']], pd.get_dummies(multi_account['bin'], prefix='dummy', drop_first=True)], axis=1))
	print(pd.concat([multi_account[['stock_code', 'corp_name', '1/PER', 'bin']], pd.get_dummies(multi_account['bin'], prefix='dummy', drop_first=False)], axis=1))


결과 값
  stock_code  corp_name     1/PER     bin  dummy_평균PER  dummy_저PER
0  005930     삼성전자      0.054612  저PER   0            1         
1  000660     SK하이닉스    0.052296  저PER   0            1         
2  035720     카카오       0.002472  고PER   0            0         
3  035420     NAVER     0.012501  평균PER  1            0         
4  051910     LG화학      0.011522  고PER   0            0         
5  051900     LG생활건강    0.029631  평균PER  1            0         
6  093050     LF        0.047819  저PER   0            1         
7  207940     삼성바이오로직스  0.004305  고PER   0            0         

  stock_code  corp_name     1/PER    bin  dummy_고PER  dummy_평균PER  dummy_저PER
0  005930     삼성전자      0.054612  저PER   0           0            1         
1  000660     SK하이닉스    0.052296  저PER   0           0            1         
2  035720     카카오       0.002472  고PER   1           0            0         
3  035420     NAVER     0.012501  평균PER  0           1            0         
4  051910     LG화학      0.011522  고PER   1           0            0         
5  051900     LG생활건강    0.029631  평균PER  0           1            0         
6  093050     LF        0.047819  저PER   0           0            1         
7  207940     삼성바이오로직스  0.004305  고PER   1           0            0

 

예시를 들기 위해 1/PER의 데이터를 고PER, 평균PER, 저PER로 나눈 범주형변수로 변환하였다. 실제로는 연속형변수가 더욱 설명력이 높을 수 있으니 변환은 테스트를 통해서 신중히 결정해야 한다. 비슷한 수준의 1/PER은 그 속에선 유의미한 차이가 없다면 범주형 변수로의 변환을 고려해볼 수 있다. 업종 데이터를 이용하는 것이 일반적이다.

 

더미변수로 변환하면 각 값을 0, 1으로 변환한 조합으로 각 값을 설명한다. 즉, 고PER은 고PER, 평균PER, 저PER의 조합이 1, 0, 0 이다. 더미변수로의 변환은 크게 두 가지가 있다 고PER, 평균PER, 저PER 모두 사용하는 경우와 평균PER, 저PER 두 가지만 사용하는 경우이다. 후자의 경우는 평균PER과 저PER의 값이 모두 0일 때 고PER을 의미한다.

728x90