반응형

살아가면서 큰 돈을 만지려면 투자 혹은 창업! 두 가지 방법밖에 없다고 생각합니다.

[투자 공부 + 코딩 공부]를 위해 투자 프로젝트를 아래와 같이 3가지 단계로 시작해봅니다.

1. Data Gathering

 

1. 데이터 종류

    1.1) 회사 데이터

      가) 회사명(완료)

      나) 종목코드(완료)

      다) 산업군(완료)

 

    1.2) 일별 KOSPI 데이터 : 

    1.3) 일별 시장지표 : 

 

    1.4) KOSPI 기업들 재무제표

    1.5) 일별 미국 증시 데이터 : To Be Updated

 

2. 수집 방법

  1. 라이브러리 : Data Gathering에 사용한 라이브러리는 다음과 같습니다.

  [FinanceDataReader, pandas_datareader, pymysql, requests, BeautifulSoup, selenium]

 

    1) FinanceDataReader(fdr) : 일반적인 금융 데이터를 수집한다. 

https://financedata.github.io/posts/finance-data-reader-users-guide.html

 

FinanceDataReader 사용자 안내서

FinanceDataReader 사용자 안내서

financedata.github.io

    2) pandas_datareader(pdr) : 일반적인 금융 데이터를 수집한다.

https://pandas-datareader.readthedocs.io/en/latest/

 

pandas-datareader — pandas-datareader 0.8.0+4.gec799a0 documentation

Usage Starting in 0.19.0, pandas no longer supports pandas.io.data or pandas.io.wb, so you must replace your imports from pandas.io with those from pandas_datareader: from pandas.io import data, wb # becomes from pandas_datareader import data, wb Many func

pandas-datareader.readthedocs.io

    3) pymysql : mysql 서버를 python을 활용하여 접근한다.(수집한 정보를 Local MYSQL 서버에 저장한다.)

    4) requests : 일반적으로 크롤링에 사용되는 라이브러리, 웹페이지에 요청을 보내고 응답을 받는다.

    5) BeautifulSoup : 일반적으로 크롤링에 사용되는 라이브러리, requests를 통해 받은 응답을 정제한다.

    6) selenium : requests로 크롤링이 불가능한 경우(ex : click이 필요할 때) 사용한다.

 

  회사 정보, KOSPI, 시장지표 대부분 데이터는 FinanceDataReader, pandas_datareader를 사용하면 데이터를 얻을 수 있습니다. 사용법은 위의 Reference를 참고하시기 바랍니다.

 

 

  2. 크롤링 :

fdr, pdr을 통해 구할 수 없는 일부 데이터(ex : 원유 가격, 재무제표)등을 구하기 위한 방법입니다. 웹페이지에서 직접 정보를 모으는 것을 말하며, requests, BeautifulSoup, selenium 라이브러리를 활용합니다.

      

      

 

2. 관계형 데이터베이스에 저장 :

MYSQL을 사용하여 관계형 데이터베이스에 저장합니다.(추후 클라우드로 이동 가능)

 

 

3. 분석 

 

데이터 수집이 완료되면 자동화시킨 후 클라우드 상에서 분석을 진행할 예정입니다.-!

 

 

반응형

'토이 프로젝트' 카테고리의 다른 글

[Step 1] 교통망 시각화하기  (0) 2018.07.27
반응형


< 교통망 시각화를 통한 교통량 파악(잠실) > 


목적 : 서울 시내 교통량의 시간대별, 종류별 분류


방법 : 1. 교통망 시각화하기

   2. CCTV 분석을 통한 교통량 파악

   3. 교통망에 교통량 더하기

   4. 통계 및 데이터 분석



[Step 1] 교통망 시각화하기

 

교통망의 시각화는 아래 사이트를 참고하였습니다.

정확히 각 패키지와 코드의 구성은 알 수 없지만, 어렴풋이 이해하려 노력했습니다.


https://junpyopark.github.io/road-network-construction-1/


박준표 님께서 올려주신 코드를 조금만 수정하면 자신이 원하는 부분의 원하는 만큼의 데이터를 추출해낼 수 있습니다. (시간이 매우 오래 걸립니다. 자세한 내용은 해당 github을 참고하시기 바랍니다.)

아래와 같이 입력을 하면 제가 사는 잠실 주위의 노드들을 연결하여 확인할 수 있습니다. 다만 저는 중첩되는 노드들을 간소화해야 하는데 이 방법은 더 찾아봐야할 것 같습니다.


import shapefile  #the pyshp module : Should install pyshp module.

import pandas as pd

from pyproj import Proj, transform  #Should install pyproj module.


# read data (Copy all files from nodelink into nodelink folder: I made it.)

# using old_data

shp_path_node = 'C:/Users/Sunghyun/Python3/Toy Project1_도로망 시각화하기/전국표준노드링크/MOCT_NODE.shp'

sf_node = shapefile.Reader(shp_path_node)

shp_path_link = 'C:/Users/Sunghyun/Python3/Toy Project1_도로망 시각화하기/전국표준노드링크/MOCT_LINK.shp'

sf_link = shapefile.Reader(shp_path_link)


# construct pandas dataframe

#grab the shapefile's field names

# node

fields_node = [x[0] for x in sf_node.fields][1:]

records_node = sf_node.records()

shps = [s.points for s in sf_node.shapes()] # node has coordinate data.

# link

fields_link = [x[0] for x in sf_link.fields][1:]

records_link = sf_link.records()


#write the records into a dataframe

#node

node_dataframe = pd.DataFrame(columns=fields_node, data=records_node)

#add the coordinate data to a column called "coords"

node_dataframe = node_dataframe.assign(coords=shps)

# link

link_dataframe = pd.DataFrame(columns=fields_link, data=records_link)


"""

광역/특별시의 권역코드(STNL_REG)는 다음과 같습니다. 


서울 : 100 ~ 124

부산 : 130 ~ 145

대구 : 150 ~ 157

인천 : 161 ~ 170

광주 : 175 ~ 179

대전 : 183 ~ 187

울산 : 192 ~ 196

"""

    

# Data restriction

range_STNL_REG=range(123, 124) # STNL_REG for Seoul

df_node = pd.DataFrame()

df_link = pd.DataFrame()

for ii in range_STNL_REG:

    res_node = node_dataframe[node_dataframe['STNL_REG'] == str(ii) ] # STNL_REG is not int.

    res_link = link_dataframe[link_dataframe['STNL_REG'] == str(ii) ]

    df_node = pd.concat([df_node,res_node],ignore_index=True) # marge data

    df_link = pd.concat([df_link,res_link],ignore_index=True)


    

# Change node name in korean

for idx,row in df_node.iterrows():

    if type(row['NODE_NAME']) == bytes :

    # row['NODE_NAME'] = row['NODE_NAME'].decode('euc_kr')

        row['NODE_NAME'] = row['NODE_NAME'].decode('cp949')

        print(row['NODE_NAME'])


# Change coordinate system

# korea 2000/central belt 2010 (epsg:5186) to wgs84(epsg:4326)

inProj = Proj(init = 'epsg:5186')

outProj= Proj(init = 'epsg:4326')

latitude = []

longitude= []

for idx,row in df_node.iterrows():

    x,y  = row.coords[0][0],row.coords[0][1]  # korea 2000 좌표계

    nx,ny = transform(inProj,outProj,x,y)     # 새로운 좌표계    

    latitude.append(ny)

    longitude.append(nx)

df_node['latitude'] = latitude

df_node['longitude']= longitude

del df_node['coords'] # delete coords


# Change column name to draw network in Gephi

df_node.rename(columns={'NODE_ID':'Id'},inplace = True)

df_link.rename(columns={'F_NODE':'Source','T_NODE':'Target'},inplace = True)


df_node.to_csv('seoul_nodes.csv') # node list

df_link.to_csv('seoul_links.csv') # edge(=link) list


import os

import folium

import pandas as pd

import numpy as np

import networkx as nx


nodes = pd.read_csv('seoul_nodes.csv', encoding = 'cp949')

links = pd.read_csv('seoul_links.csv')

#nodes = nodes[['Id','NODE_NAME','latitude','longitude']]

links = links[['Source','Target']]

links.head()


source_in = links['Source'].apply(lambda x : x in list(nodes['Id'])) # check Sources are in incheon_id

target_in = links['Target'].apply(lambda x : x in list(nodes['Id'])) # check Targets are in incheon_id

# source_in and target_in are boolean type pandas.Series which contains True or False

seoul_links = links[source_in & target_in] # contain if both target and source are contained in incheon_id


G = nx.Graph()

# R is the Earth's radius

R = 6371e3


for idx,row in nodes.iterrows():

    # add node to Graph G

    G.add_node(row['Id'],Label=row['NODE_NAME'],latitude=row['latitude'], longitude=row['longitude'])


for idx,row in seoul_links.iterrows():

    ## Calculate the distance between Source and Target Nodes

    lon1 = float(nodes[nodes['Id'] == row['Source']]['longitude'] * np.pi/180)

    lat1 = float(nodes[nodes['Id'] == row['Source']]['latitude'] * np.pi/180)

    lon2 = float(nodes[nodes['Id'] == row['Target']]['longitude'] * np.pi/180)

    lat2 = float(nodes[nodes['Id'] == row['Target']]['latitude'] * np.pi/180)

    d_lat = lat2 - lat1

    d_lon = lon2 - lon1

    a = np.sin(d_lat/2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(d_lon/2) ** 2

    c = 2 * np.arctan2(a**0.5, (1-a) ** 0.5)

    d = R * c

    

    # Link attribute : 'Source', 'Target' and weight = 'Length between them'

    G.add_edge(row['Source'],row['Target'],weight = d)

    

# Positioning the Standard Point for our Folium Map

std_point = tuple(nodes.head(1)[['latitude','longitude']].iloc[0])

std_point    


map_osm = folium.Map(location=std_point, zoom_start=10) 

# location : 기준이 되는 점, zoom_start : 지도 상의 zoom level 을 나타냅니다.


for ix, row in nodes.iterrows():

    location = (row['latitude'], row['longitude']) # 위도, 경도 튜플

    folium.Circle(

        location=location,

        radius=G.degree[row['Id']] * 30, # 지름이 degree에 비례하도록 설정

        color='white',

        weight=1,

        fill_opacity=0.6,

        opacity=1,

        fill_color='red',

        fill=True,  # gets overridden by fill_color

        # popup=str(row['Id'])

    ).add_to(map_osm)

    # folium.Marker(location, popup=row['NODE_NAME']).add_to(map_osm)


    

kw = {'opacity': 0.5, 'weight': 2}

for ix, row in seoul_links.iterrows():

    start = tuple(nodes[nodes['Id']==row['Source']][['latitude','longitude']].iloc[0])

    end = tuple(nodes[nodes['Id']==row['Target']][['latitude','longitude']].iloc[0])

    folium.PolyLine(

        locations=[start, end],

        color='blue',

        line_cap='round',

        **kw,

    ).add_to(map_osm)

# it takes some time.....

map_osm




< 위의 작업을 실행하며 발생한 문제들 > 


Issue 1) Tistory에 임시저장을 한 후 다시 확인을 해보니 보이지 않아 인터넷으로 검색해보니 임시저장 기능이 완벽하지 않은 것 같습니다.


저와 같이 Chrome을 사용하시는 분들은 


chrome://settings/content -> flash -> 허용 사이트에 자신의 티스토리 주소를 추가해줍니다.


이렇게 추가한 뒤에 임시저장을 위해 본인의 사이트를 다시 실행하게 되면, 임시저장 버튼 위에 퍼즐 모양의 아이콘이 나타나게 됩니다.


이 버튼을 클릭 후 이번만 실행 버튼을 누르게 되면, 임시 저장 관련된 버튼 및 기능이 제대로 작동하게 됩니다.


Issue 2) pip를 통해 다른 패키지들을 설치하는데 문제가 있습니다. pip install pyshp 를 실행했을 때 [transport_encoding] 관련 Type_Error 


가 발견됩니다. 이를 해결하기 위해서 python이 설치된 경로로 들어가 pip 패키지 폴더를 찾습니다.


ex) 저의 경우는 C:\Users\사용자명\Anaconda3\Lib\site-packages\pip 입니다.


pip 폴더 내의 index.py 파일에서 transport_encoding=encoding, 이란 항목이 있는데 이 줄을 주석처리하면 해당 Error를 없앨 수 있습니다. 


다만 이 주석처리가 어떤 결과를 불러올진 잘 모르겠으니 에러가 발생한다면 해당 파라미터를 주석처리했다는 것을 생각해보시길..


Issue 3) distutils.errors.DistutilsPlatformError: Unable to find vcvarsall.bat 


  pyproj 패키지를 설치하려고 하는데 위와 같은 오류가 발생했습니다. 해당 패키지를 설치하려면 Visual Studio C++ 관련 Build Tool 이 깔려


있어야 한다고 합니다. 이를 위해 다음 링크를 통해 Tool 만 다운받아 설치합니다.


https://visualstudio.microsoft.com/ko/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15


이후 패키지 설치를 다시 시도하면 완료!


Issue 3csv 파일을 저장하고 Pandas 라이브러리를 통해 불러오려 했을 때, 아래와 같은 에러에 직면합니다.


UnicodeDecodeError: 'utf-8' codec can't decode byte 0xba in position 0: invalid start byte

이 에러는 encoding type과 decoding type이 다르기 때문에 발생하는 에러입니다. 따라서 read_csv('file_name.csv', encoding = 'cp949')과 같이 인코딩 type을 파라미터로 전달해주면 해결됩니다! 저의 경우에는 encoding type을 cp949(eur_kr이나 다른 방식으로 encoding하셔도 같은 방법으로 decoding하시면 됩니다.)으로 전달해줘서 해결하였습니다. 이 인자에 아무것도 전달하지 않으면 'utf-8' 방식으로 decoding 합니다.



반응형

'토이 프로젝트' 카테고리의 다른 글

가치투자 프로젝트 (1) Data Gathering  (0) 2020.03.10

+ Recent posts