본문 바로가기

Data Science/Data Preprocessing

[03. Feature Engineering] 004. Transform

728x90

다양한 데이터가 있다. 모델에 사용하는 데이터를 그대로 쓰면 의미가 이상해지는 경우가 있다. 예를 들어 주식시장에서의 PER은

 

시가총액 / 당기순이익

 

이며 PER이 낮을수록 저평가 기업으로 여겨진다. 하지만 당기순이익이 –인 적자상태라면? -10이 1보다 좋은 기업이라고 말할 수 없을 것이다. 이런 경우에는 간단히 역수를 취하면 된다.

 

1 / PER = 당기순이익 / 시가총액

 

이는 이익수익률이라고 불리며, 당기순이익이 높을수록 양의 값이 커지며 적자폭이 깊어질수록 음의 값이 커진다. 당기순이익이 높을수록 좋은 기업이며 적자가 심해질수록 좋지 않은 기업이다라고 해석할 수 있으며 이는 시가총액 대비 당기순이익이 높은 기업은 저평가라는 의미와 맞아 떨어진다. 따라서 있는 그대로의 데이터를 사용하는 것 보다 변환을 하는 것이 분석에 더 도움된다.

 

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']
    print(multi_account[['stock_code', 'corp_name', 'PER', '1/PER']])


결과 값
  stock_code  corp_name         PER     1/PER
0  005930     삼성전자      18.310947   0.054612
1  000660     SK하이닉스    19.122073   0.052296
2  035720     카카오       404.597559  0.002472
3  035420     NAVER     79.993659   0.012501
4  051910     LG화학      86.791187   0.011522
5  051900     LG생활건강    33.748815   0.029631
6  093050     LF        20.911994   0.047819
7  207940     삼성바이오로직스  232.288190  0.004305
728x90