10wk-1: 야후 finance, 출산율 자료 시각화

plotly
Author

최규빈

Published

November 6, 2023

1. 강의영상

2. Imports

# !pip install yfinance
import numpy as np 
import pandas as pd 
import yfinance as yf

3. yfinance를 이용한 주식자료 시각화

A. 크롤링 + 데이터정리

- yahoo finance: https://finance.yahoo.com/

Apple: 'AAPL'

Apple 코드

삼성전자: '005930.KS'

삼성전자 코드

- 크롤링을 위한 코드

symbols = ['AMZN','AAPL','GOOG','MSFT','NFLX','NVDA','TSLA']
start = '2020-01-01'
end = '2023-11-06'
df = yf.download(symbols,start,end)
df
[                       0%%                      ][**************        29%%                      ]  2 of 7 completed[********************* 43%%                      ]  3 of 7 completed[**********************57%%*                     ]  4 of 7 completed[**********************71%%********              ]  5 of 7 completed[**********************86%%***************       ]  6 of 7 completed[*********************100%%**********************]  7 of 7 completed
Adj Close Close ... Open Volume
AAPL AMZN GOOG MSFT NFLX NVDA TSLA AAPL AMZN GOOG ... NFLX NVDA TSLA AAPL AMZN GOOG MSFT NFLX NVDA TSLA
Date
2020-01-02 73.152657 94.900497 68.368500 154.779526 329.809998 59.744045 28.684000 75.087502 94.900497 68.368500 ... 326.100006 59.687500 28.299999 135480400 80580000 28132000 22622100 4485800 23753600 142981500
2020-01-03 72.441467 93.748497 68.032997 152.852249 325.899994 58.787781 29.534000 74.357498 93.748497 68.032997 ... 326.779999 58.775002 29.366667 146322800 75288000 23728000 21116200 3806900 20538400 266677500
2020-01-06 73.018700 95.143997 69.710503 153.247330 335.829987 59.034309 30.102667 74.949997 95.143997 69.710503 ... 323.119995 58.080002 29.364668 118387200 81236000 34646000 20813700 5663100 26263600 151995000
2020-01-07 72.675278 95.343002 69.667000 151.850067 330.750000 59.749020 31.270666 74.597504 95.343002 69.667000 ... 336.470001 59.549999 30.760000 108872000 80898000 30054000 21634100 4703200 31485600 268231500
2020-01-08 73.844345 94.598503 70.216003 154.268814 339.260010 59.861080 32.809334 75.797501 94.598503 70.216003 ... 331.489990 59.939999 31.580000 132079200 70160000 30560000 27746500 7104500 27710800 467164500
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2023-10-30 170.065933 132.710007 125.750000 336.626770 410.079987 411.573792 197.360001 170.289993 132.710007 125.750000 ... 402.350006 410.869995 209.279999 51131000 72485500 24165600 22828100 5317100 38802800 136448200
2023-10-31 170.545319 133.089996 125.300003 337.425140 411.690002 407.764130 200.839996 170.770004 133.089996 125.300003 ... 409.239990 404.500000 196.119995 44846000 51589400 21123400 20265300 3877600 51796900 118068300
2023-11-01 173.741104 137.000000 127.570000 345.369019 420.190002 423.212799 205.660004 173.970001 137.000000 127.570000 ... 414.769989 408.839996 204.039993 56934900 61529400 26536600 28158800 4806100 43759300 121661700
2023-11-02 177.336380 138.070007 128.580002 347.614471 424.709991 435.021759 218.509995 177.570007 138.070007 128.580002 ... 421.170013 433.279999 212.970001 77334800 52236700 24091700 24348100 4476000 40917200 125987600
2023-11-03 176.417572 138.600006 130.369995 352.085388 432.359985 450.010406 219.960007 176.649994 138.600006 130.369995 ... 428.760010 440.200012 221.149994 79763700 44007200 19517900 23624000 3664800 42385500 119281000

968 rows × 42 columns

- 데이터를 살펴보자.

df.stack()
Adj Close Close High Low Open Volume
Date
2020-01-02 AAPL 73.152657 75.087502 75.150002 73.797501 74.059998 135480400
AMZN 94.900497 94.900497 94.900497 93.207497 93.750000 80580000
GOOG 68.368500 68.368500 68.406998 67.077499 67.077499 28132000
MSFT 154.779526 160.619995 160.729996 158.330002 158.779999 22622100
NFLX 329.809998 329.809998 329.980011 324.779999 326.100006 4485800
... ... ... ... ... ... ... ...
2023-11-03 GOOG 130.369995 130.369995 130.729996 129.009995 129.089996 19517900
MSFT 352.085388 352.799988 354.390015 347.329987 349.630005 23624000
NFLX 432.359985 432.359985 434.820007 425.529999 428.760010 3664800
NVDA 450.010406 450.049988 453.089996 437.230011 440.200012 42385500
TSLA 219.960007 219.960007 226.369995 218.399994 221.149994 119281000

6776 rows × 6 columns

ChatGPT

“Adj Close”는 “Adjusted Closing Price”를 의미합니다. 주식 시장에서 각 거래일의 마감 가격을 조정하여 나타낸 값입니다. “조정”이라는 용어는 주식 분할, 배당금 지급, 자본 변동과 같은 기업 활동을 반영하여 가격을 수정한 것을 의미합니다. 이는 투자자들이 시간이 지나면서 주식의 실제 성과를 더 정확히 비교할 수 있게 해줍니다.

“Close”는 해당 거래일에 주식 시장이 닫힐 때의 주식 가격입니다.

다른 열은 다음을 의미합니다:

  • “High”는 해당 거래일에 주식이 거래된 최고 가격입니다.
  • “Low”는 해당 거래일에 주식이 거래된 최저 가격입니다.
  • “Open”은 주식 시장이 개장했을 때의 주식 가격입니다.
  • “Volume”은 그 날에 거래된 주식의 총 수량입니다.

표는 다양한 날짜에 대한 여러 주요 기술 회사들(예: AAPL - Apple Inc., AMZN - Amazon.com Inc., GOOG - Alphabet Inc., MSFT - Microsoft Corporation, NFLX - Netflix Inc., NVDA - NVIDIA Corporation, TSLA - Tesla Inc.)의 주식 정보를 보여줍니다.

- Adj Close만을 선택

df.stack().loc[:,'Adj Close']
Date            
2020-01-02  AAPL     73.152657
            AMZN     94.900497
            GOOG     68.368500
            MSFT    154.779526
            NFLX    329.809998
                       ...    
2023-11-03  GOOG    130.369995
            MSFT    352.085388
            NFLX    432.359985
            NVDA    450.010406
            TSLA    219.960007
Name: Adj Close, Length: 6776, dtype: float64

- Adj Close만을 선택 – 또 다른 방법 (일단 이거로 할게요)

df.loc[:,'Adj Close']
AAPL AMZN GOOG MSFT NFLX NVDA TSLA
Date
2020-01-02 73.152657 94.900497 68.368500 154.779526 329.809998 59.744045 28.684000
2020-01-03 72.441467 93.748497 68.032997 152.852249 325.899994 58.787781 29.534000
2020-01-06 73.018700 95.143997 69.710503 153.247330 335.829987 59.034309 30.102667
2020-01-07 72.675278 95.343002 69.667000 151.850067 330.750000 59.749020 31.270666
2020-01-08 73.844345 94.598503 70.216003 154.268814 339.260010 59.861080 32.809334
... ... ... ... ... ... ... ...
2023-10-30 170.065933 132.710007 125.750000 336.626770 410.079987 411.573792 197.360001
2023-10-31 170.545319 133.089996 125.300003 337.425140 411.690002 407.764130 200.839996
2023-11-01 173.741104 137.000000 127.570000 345.369019 420.190002 423.212799 205.660004
2023-11-02 177.336380 138.070007 128.580002 347.614471 424.709991 435.021759 218.509995
2023-11-03 176.417572 138.600006 130.369995 352.085388 432.359985 450.010406 219.960007

968 rows × 7 columns

B. 시각화

- tidydata를 생성

df.loc[:,'Adj Close'].stack().reset_index()\
.set_axis(['Date','Company','Price'],axis=1)
Date Company Price
0 2020-01-02 AAPL 73.152657
1 2020-01-02 AMZN 94.900497
2 2020-01-02 GOOG 68.368500
3 2020-01-02 MSFT 154.779526
4 2020-01-02 NFLX 329.809998
... ... ... ...
6771 2023-11-03 GOOG 130.369995
6772 2023-11-03 MSFT 352.085388
6773 2023-11-03 NFLX 432.359985
6774 2023-11-03 NVDA 450.010406
6775 2023-11-03 TSLA 219.960007

6776 rows × 3 columns

- 바로 이어서 시각화! – x='Date', y='Price', color='Company'

df.loc[:,'Adj Close'].stack().reset_index()\
.set_axis(['Date','Company','Price'],axis=1)\
.plot.line(x='Date',y='Price',color='Company',backend='plotly')
/home/cgb2/anaconda3/envs/ag/lib/python3.10/site-packages/_plotly_utils/basevalidators.py:105: FutureWarning:

The behavior of DatetimeProperties.to_pydatetime is deprecated, in a future version this will return a Series containing python datetime objects instead of an ndarray. To retain the old behavior, call `np.array` on the result

4. 출산율 시각화

A. 크롤링 + 데이터정리

- 대한민국의 저출산문제

ref: https://ko.wikipedia.org/wiki/대한민국의_저출산

- 위의 url에서 5번째 테이블을 읽고싶다.

  • 5번째 테이블: 시도별 출생아 수
df_lst = pd.read_html('https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EC%9D%98_%EC%A0%80%EC%B6%9C%EC%82%B0')
df = df_lst[4]
df
지역/연도[6] 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
0 서울 93266 91526 93914.000 84066.000 83711.000 83005 75.536 65389 58074 53.673 47400 45531
1 부산 27415 27759 28673.000 25831.000 26190.000 26645 24906.000 21480 19152 17049.000 15100 14446
2 대구 20557 20758 21472.000 19340.000 19361.000 19438 18298.000 15946 14400 13233.000 11200 10661
3 인천 25752 20758 21472.000 25560.000 25786.000 25491 23609.000 20445 20087 18522.000 16000 14947
4 광주 13979 13916 14392.000 12729.000 12729.000 12441 11580.000 10120 9105 8364.000 7300 7956
5 대전 14314 14808 15279.000 14099.000 13962.000 13774 12436.000 10851 9337 8410.000 7500 7414
6 울산 11432 11542 12160.000 11330.000 11556.000 11732 10910.000 9381 8149 7539.000 6600 6127
7 세종 - - 1054.000 1111.000 1344.000 2708 3297.000 3504 3703 3819.000 3500 3570
8 경기 121753 122027 124746.000 112129.000 112.169 113495 105643.000 94088 83198 83.198 77800 76139
9 강원 12477 12408 12426.000 10980.000 10662.000 10929 10058.000 9958 8351 8283.000 7800 7357
10 충북 14670 14804 15139.000 13658.000 13366.000 13563 12742.000 11394 10586 9333.000 8600 8190
11 충남 20.242 20.398 20.448 18.628 18200.000 18604 17302.000 15670 14380 13228.000 11900 10984
12 전북 16100 16175 16238.000 14555.000 14231.000 14087 12698.000 11348 10001 8971.000 8200 7745
13 전남 16654 16612 16990.000 15401.000 14817.000 15061 13980.000 12354 11238 10832.000 9700 8430
14 경북 23700 24250 24635.000 22206.000 22062.000 22310 20616.000 17957 16079 14472.000 12900 12045
15 경남 32203 32536 33211.000 29504.000 29763.000 29537 27138.000 23849 21224 19250.000 16800 15562
16 제주 5657 5628 5992.000 5328.000 5526.000 5600 5494.000 5037 4781 4500.000 4000 3728
17 전국 470171 471265 484550.000 436455.000 435435.000 438420 406243.000 357771 326822 302676.000 272400 260562

- '-'로 표현된 값을 0으로 처리하는게 좋겠음

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).reset_index()
/tmp/ipykernel_1174230/1737303492.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.
지역 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
0 서울 93266.000 91526.000 93914.000 84066.000 83711.000 83005.0 75.536 65389.0 58074.0 53.673 47400.0 45531.0
1 부산 27415.000 27759.000 28673.000 25831.000 26190.000 26645.0 24906.000 21480.0 19152.0 17049.000 15100.0 14446.0
2 대구 20557.000 20758.000 21472.000 19340.000 19361.000 19438.0 18298.000 15946.0 14400.0 13233.000 11200.0 10661.0
3 인천 25752.000 20758.000 21472.000 25560.000 25786.000 25491.0 23609.000 20445.0 20087.0 18522.000 16000.0 14947.0
4 광주 13979.000 13916.000 14392.000 12729.000 12729.000 12441.0 11580.000 10120.0 9105.0 8364.000 7300.0 7956.0
5 대전 14314.000 14808.000 15279.000 14099.000 13962.000 13774.0 12436.000 10851.0 9337.0 8410.000 7500.0 7414.0
6 울산 11432.000 11542.000 12160.000 11330.000 11556.000 11732.0 10910.000 9381.0 8149.0 7539.000 6600.0 6127.0
7 세종 0.000 0.000 1054.000 1111.000 1344.000 2708.0 3297.000 3504.0 3703.0 3819.000 3500.0 3570.0
8 경기 121753.000 122027.000 124746.000 112129.000 112.169 113495.0 105643.000 94088.0 83198.0 83.198 77800.0 76139.0
9 강원 12477.000 12408.000 12426.000 10980.000 10662.000 10929.0 10058.000 9958.0 8351.0 8283.000 7800.0 7357.0
10 충북 14670.000 14804.000 15139.000 13658.000 13366.000 13563.0 12742.000 11394.0 10586.0 9333.000 8600.0 8190.0
11 충남 20.242 20.398 20.448 18.628 18200.000 18604.0 17302.000 15670.0 14380.0 13228.000 11900.0 10984.0
12 전북 16100.000 16175.000 16238.000 14555.000 14231.000 14087.0 12698.000 11348.0 10001.0 8971.000 8200.0 7745.0
13 전남 16654.000 16612.000 16990.000 15401.000 14817.000 15061.0 13980.000 12354.0 11238.0 10832.000 9700.0 8430.0
14 경북 23700.000 24250.000 24635.000 22206.000 22062.000 22310.0 20616.000 17957.0 16079.0 14472.000 12900.0 12045.0
15 경남 32203.000 32536.000 33211.000 29504.000 29763.000 29537.0 27138.000 23849.0 21224.0 19250.000 16800.0 15562.0
16 제주 5657.000 5628.000 5992.000 5328.000 5526.000 5600.0 5494.000 5037.0 4781.0 4500.000 4000.0 3728.0
17 전국 470171.000 471265.000 484550.000 436455.000 435435.000 438420.0 406243.000 357771.0 326822.0 302676.000 272400.0 260562.0

B. 시각화1: 전국 출생아수 시각화

- 전국으로 집계가 되어있던 정보를 남겨도 좋지만, groupy+agg 조합으로 새롭게 계산해보자.

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).drop('전국')\
.stack().reset_index().rename({'level_1':'년도',0:'출생아수'},axis=1)\
.groupby('년도').agg({'출생아수':'sum'}).reset_index()\
.plot.line(x='년도',y='출생아수',backend='plotly')
/tmp/ipykernel_1174230/1805618332.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

C. 시각화2: 시도별 출생아수 시각화 (line)

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).drop('전국')\
.stack().reset_index().rename({'level_1':'년도',0:'출생아수'},axis=1)\
.plot.line(x='년도',y='출생아수',color='지역',backend='plotly')
/tmp/ipykernel_1174230/277281482.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

D. 시각화3: 시도별 출생아수 시각화 (area)

- 시각화1,시각화2의 정보가 적절히 혼합되어있는 시각화는 없을까?

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).drop('전국')\
.stack().reset_index().rename({'level_1':'년도',0:'출생아수'},axis=1)\
.plot.area(x='년도',y='출생아수',color='지역',backend='plotly')
/tmp/ipykernel_1174230/70633050.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.
  • 기묘하다..

- 해석: 2014년 경기, 2016년 서울, 2019년 경기에 애를 낳지 않는다.

- 데이터와 비교

df
지역/연도[6] 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
0 서울 93266 91526 93914.000 84066.000 83711.000 83005 75.536 65389 58074 53.673 47400 45531
1 부산 27415 27759 28673.000 25831.000 26190.000 26645 24906.000 21480 19152 17049.000 15100 14446
2 대구 20557 20758 21472.000 19340.000 19361.000 19438 18298.000 15946 14400 13233.000 11200 10661
3 인천 25752 20758 21472.000 25560.000 25786.000 25491 23609.000 20445 20087 18522.000 16000 14947
4 광주 13979 13916 14392.000 12729.000 12729.000 12441 11580.000 10120 9105 8364.000 7300 7956
5 대전 14314 14808 15279.000 14099.000 13962.000 13774 12436.000 10851 9337 8410.000 7500 7414
6 울산 11432 11542 12160.000 11330.000 11556.000 11732 10910.000 9381 8149 7539.000 6600 6127
7 세종 - - 1054.000 1111.000 1344.000 2708 3297.000 3504 3703 3819.000 3500 3570
8 경기 121753 122027 124746.000 112129.000 112.169 113495 105643.000 94088 83198 83.198 77800 76139
9 강원 12477 12408 12426.000 10980.000 10662.000 10929 10058.000 9958 8351 8283.000 7800 7357
10 충북 14670 14804 15139.000 13658.000 13366.000 13563 12742.000 11394 10586 9333.000 8600 8190
11 충남 20.242 20.398 20.448 18.628 18200.000 18604 17302.000 15670 14380 13228.000 11900 10984
12 전북 16100 16175 16238.000 14555.000 14231.000 14087 12698.000 11348 10001 8971.000 8200 7745
13 전남 16654 16612 16990.000 15401.000 14817.000 15061 13980.000 12354 11238 10832.000 9700 8430
14 경북 23700 24250 24635.000 22206.000 22062.000 22310 20616.000 17957 16079 14472.000 12900 12045
15 경남 32203 32536 33211.000 29504.000 29763.000 29537 27138.000 23849 21224 19250.000 16800 15562
16 제주 5657 5628 5992.000 5328.000 5526.000 5600 5494.000 5037 4781 4500.000 4000 3728
17 전국 470171 471265 484550.000 436455.000 435435.000 438420 406243.000 357771 326822 302676.000 272400 260562

E. 시각화1,2,3 수정

- 시각화1의 수정

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).drop('전국')\
.applymap(lambda x: x*1000 if x<1000 else x)\
.stack().reset_index().rename({'level_1':'년도',0:'출생아수'},axis=1)\
.groupby('년도').agg({'출생아수':'sum'}).reset_index()\
.plot.line(x='년도',y='출생아수',backend='plotly')
/tmp/ipykernel_1174230/1274971694.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

/tmp/ipykernel_1174230/1274971694.py:4: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

- 시각화2의 수정

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).drop('전국')\
.applymap(lambda x: x*1000 if x<1000 else x)\
.stack().reset_index().rename({'level_1':'년도',0:'출생아수'},axis=1)\
.plot.line(x='년도',y='출생아수',color='지역',backend='plotly')
/tmp/ipykernel_1174230/1526382732.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

/tmp/ipykernel_1174230/1526382732.py:4: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

- 시각화3의 수정

df.rename({'지역/연도[6]':'지역'},axis=1)\
.set_index(['지역'])\
.applymap(lambda x: 0 if '-' in str(x) else float(x)).drop('전국')\
.applymap(lambda x: x*1000 if x<1000 else x)\
.stack().reset_index().rename({'level_1':'년도',0:'출생아수'},axis=1)\
.plot.area(x='년도',y='출생아수',color='지역',backend='plotly')
/tmp/ipykernel_1174230/3339566067.py:3: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

/tmp/ipykernel_1174230/3339566067.py:4: FutureWarning:

DataFrame.applymap has been deprecated. Use DataFrame.map instead.

5. HW

삼성전자와 카카오에 대한 주가('Adj Close' 기준)를 아래와 같이 시각화 하라.

  • start = ‘2020-01-01’
  • end = ‘2023-11-06’

시각화예시