2021 캐글 대회 코드 작성기 - 1

파이썬을 배운지 며칠 되지 않아 kaggle이라는 예측모델 및 분석대회 플랫폼의 데이터 분석 대회에 참가하게 되었다.
주제는 2021년 캐글러kaggler들에게 설문조사이며, 그 설문조사 데이터셋을 바탕으로 참가자가 분석을 하여 참가자만의 주제에 그래프와 수치로 답을 찾아내는 대회이다.

데이터셋에 있는 캐글러의 수는 19년 19717명, 21년 25974명, 직업은 데이터사이언스, 데이터 엔지니어부터 학생까지 다양하며, 나이, 학력, 국적, 라이브러리, 언어 등 매우 다양한 항목들이 있다.

우리 조에서 처음으로 선정하려 했던 주제는 한국, 일본, 중국의 캐글러의 트렌드변화로 하려 했으나, 중국, 일본에 비해 데이터가 턱없이 부족해 비교가 무의미한 수준이었기에 캐글러의 수가 비슷한 두 나라인 중국과 일본로 선정했다.(의외로 중국의 캐글러 절대적인 수가 인구에 비해 상당히 적어 일본보다 조금 적은편이였다.)

import(Kaggle notebook)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np 
import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from warnings import filterwarnings
from plotly.subplots import make_subplots
filterwarnings('ignore')

colors = ['#B1EDED','#B1B2ED','#1DE7ED','#1DA5ED','#1D50ED','#16548E']
gen_colors = ['#4169E1','#B2182B','#81007F','#D1B2FF','#EFE4E2']
JP_colors = ['#D90B0B','#F24444','#EFE4E2','#FCCE88','#64807F']
CN_colors = ['#E0201B','#FFCE3F','#A63F03','#04BF33','#F2E6D8']
coun_years_colors = ['#D90B0B','#FFCE3F','#FF6161','#FFDB81']

df19 = pd.read_csv('../input/kaggle-survey-2019/multiple_choice_responses.csv')
df21 = pd.read_csv('../input/kaggle-survey-2021/kaggle_survey_2021_responses.csv')

이처럼 후에 사용할 라이브러리를 임포트, 그래프에 사용할 색을 리스트로 만들어주고 df19에 19년의 데이터셋을, df21에 21년의 데이터셋을 넣어준다.

사용자 지정 함수


1
2
3
4
5
6
7
8
9
10
def group(data, country, question_num):
return data[data['Q3'] == country][question_num].value_counts()

def go_Pie(country, label_value):
return go.Pie(title = country,
labels = label_value.index,
values = label_value.values,
textinfo = 'label+percent',
rotation=315,
hole = .3,)

앞으로 코드에서 사용될 함수이다.
사용자 지정 함수란?

Q1. What`s your age?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
JP_age_19 = group(df19,'Japan','Q1').sort_index()

JP_age_21 = group(df21,'Japan','Q1').sort_index()

CN_age_19 = group(df19,'China','Q1')
CN_age_19.loc['55-59'] = 0
CN_age_19.loc['60-69'] = 0
CN_age_19 = CN_age_19.sort_index()

CN_age_21 = group(df21,'China','Q1')
CN_age_21.loc['60-69'] = 0
CN_age_21 = CN_age_21.sort_index()

fig_age = make_subplots(rows=1, cols=2, specs=[[{'type':'xy'}, {'type':'xy'}]])

fig_age.add_trace(go.Bar(name=coun_years[0], x=JP_age_19.index, y=JP_age_19.values, marker_color='#FDB0C0'),1,1)
fig_age.add_trace(go.Bar(name=coun_years[2], x=JP_age_21.index, y=JP_age_21.values, marker_color='#FD4659'),1,1)
fig_age.add_trace(go.Bar(name=coun_years[1], x=CN_age_19.index, y=CN_age_19.values, marker_color='#FFDB81'),1,2)
fig_age.add_trace(go.Bar(name=coun_years[3], x=CN_age_21.index, y=CN_age_21.values, marker_color='#FFAB0F'),1,2)

fig_age.update_layout(barmode='group', title_text='2019 & 2021, Japan and China age distribution', showlegend=True)

fig_age.update_xaxes(title_text='Japan Age distribution', row=1, col=1)
fig_age.update_yaxes(title_text='Counts', row=1, col=1)
fig_age.update_xaxes(title_text='China Age distribution', row=1, col=2)
fig_age.update_yaxes(title_text='Counts', row=1, col=2)

fig_age.show()

일본, 중국 캐글러의 나이분포

첫번째 주제인 What`s your age?에 대한 일본과 중국의 캐글러 나이분포를 막대그래프로 나타낸 것이다.
각 그래프는 연도별로 나눈 일,중 캐글러의 나이 분포이고 그래프의 항목은 18세부터 70세 이상까지 3,4년씩을 한 항목으로 묶었다.

Q2. What`s your gender?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
JP_ndarray = df19[df19['Q3'] == 'Japan']['Q2'].values
CN_ndarray = df19[df19['Q3'] == 'China']['Q2'].values
JP_age_list = []
CN_age_list = []

for item in JP_ndarray:
if item == 'Male':
item_mod = item.replace('Male','Man')
JP_age_list.append(item_mod)
elif item == 'Female':
item_mod2 = item.replace('Female','Woman')
JP_age_list.append(item_mod2)
else :
JP_age_list.append(item)

for item in CN_ndarray:
if item == 'Male':
item_mod = item.replace('Male','Man')
CN_age_list.append(item_mod)
elif item == 'Female':
item_mod2 = item.replace('Female','Woman')
else :
CN_age_list.append(item)

JP_age_series = pd.Series(JP_age_list)
CN_age_series = pd.Series(CN_age_list)

fig = make_subplots(rows=2, cols=2, specs=[[{'type':'domain'}, {'type':'domain'}],
[{'type':'domain'}, {'type':'domain'}]])

fig.add_trace(go_Pie('2019_Japan', JP_age_series.value_counts()),1,1)
fig.add_trace(go_Pie('2019_China', CN_age_series.value_counts()),1,2)
fig.add_trace(go_Pie('2021_Japan', group(df21,'Japan','Q2')),2,1)
fig.add_trace(go_Pie('2021_China', group(df21,'China','Q2')),2,2)

fig.update_traces(marker=dict(colors=gen_colors[0:]))
fig.update_layout(title_text='Gender Distribution',
showlegend=True,
autosize=True,
height=700)
fig.show()

일본, 중국 캐글러의 성별분포

두번쨰 질문에 답하기 위해 일본과 중국의 캐글러 성별분포를 도넛모양으로 나타낸 그래프이다.
각각의 그래프는 국가,년도(2019, 2021)별로 각각 나누었고 그래프의 항목은
Man
Woman
Prefer not to say
Nonbinary
Prefer to self-describe
이렇게 다섯가지로 나누었다.

References

plotly bar chart tutorial
plotly bar chart properties (bar traces)
plotly pie chart tutorial
plotly pie chart properties (pie traces)

산점도(scatter plot)와 박스플롯(box plot)

산점도(scatter plot)

산점도란?


산점도

산점도, 산포도scatter plot는 직교좌표계를 이용해 좌표상의 점들을 표시함으로써 두 개 변수 간의 관계를 나타내는 그래프 방법이다.
도표 위에 두 변수 X와 Y값이 만나는 지점을 표시한 그림. 이 그림을 통해 두 변수 사이의 관계를 알 수 있다.



언제 사용되는가??


산점도는 다음의 경우에 사용된다.

  1. 두 종류의 데이터의 관계를 파악할때. 즉, 양의 상관관계, 음의 상관관계, 관계없음 등의 관계를 파악한다.
  2. 산점도의 작성으로 한 변수에 대한 결과의 영향조사를 한다.



Plotly로 산점도 작성하기


  • 데이터 임포트 및 데이터셋 생성

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import numpy as np
    import pandas as pd
    # plotly 라이브러리 불러오기
    import plotly.offline as po
    import plotly.graph_objs as go

    # 임의의 숫자로 이루어진 2열,100행의 데이터프레임 생성
    df1 = pd.DataFrame(np.random.randint(0, 100, (100, 2)), columns=['A', 'B'])
    df2 = pd.DataFrame(np.random.randint(0, 100, (100, 2)), columns=['A', 'B'])
  • 하나의 산점도 그리기

1
2
3
trace1 = go.Scatter(x=df1['A'], y=df1['B'], mode='markers')
data = [trace1]
pyo.iplot(data)
Output

df1이 그대로 산점도로 출력된 모습이다.

  • 두 개 이상의 산점도 그리기

1
2
3
4
trace1 = go.Scatter(x=df1['A'], y=df1['B'], mode='markers')
trace2 = go.Scatter(x=df2['A'], y=df2['B'], mode='markers')
data = [trace1, trace2]
pyo.iplot(data)
Output

df1과 df2가 한 도표 내에 산점도로 출력된 모습이다.
이렇게 다른 데이터를 표시하고 싶을때에는 출력코드에 새로운 데이터값을 넣어주기만 하면 된다.

  • 마커 모양 변경하기

1
2
3
4
trace1 = go.Scatter(x=df1['A'], y=df1['B'], mode='markers', marker=dict(size=7, color='#D90B0B', symbol=20))
trace2 = go.Scatter(x=df2['A'], y=df2['B'], mode='markers', marker=dict(size=7, color='#F24444', symbol=23))
data = [trace1, trace2]
pyo.iplot(data)
Output

그림처럼 마커의 모양을 변경 할 수 있다.
color옵션은 헥스코드와 rgb값 모두 가능하며, 모양의 경우 매우 다양하므로 포스팅 최하단에 링크를 첨부한다.




박스플롯 (box plot)

박스플롯이란??


박스플롯

‘박스플롯’box plot,또는 ‘상자 수염 그림’은 수치적 자료를 나타내는 그래프이다. 이 그래프는 가공하지 않은 자료 그대로를 이용하여 그린 것이 아니라, 자료로부터 얻어낸 통계량인 ‘5가지 요약 수치’five-number summary 를 가지고 그린다. 이 때 5갸지 요약 수치란 최솟값, 제 1사분위(Q1),제 2사분위(Q2), 제 3사분위(Q3), 최댓값을 일컫는 말이다. 히스토그램과는 다르게 집단이 여러개인 경우에도 한 공간에 수월하게 나타낼수 있다.



언제 사용되는가??


박스 플롯을 사용하는 이유는 데이터가 매우 많을때 모든 데이터를 한눈에 확인하기 어려우니 그림을 이용해 데이터 집합의 범위와 중앙값을 빠르게 확인 할 수 있는 목적으로 사용한다.
또한, 통계적으로 이상치outlier가 있는지도 확인이 가능하다.



박스플롯의 구성


박스플롯을 처음 접한다면 박스플롯을 어떻게 해석해야 하는지 난해할수 있다.
다음 그림에서 박스플롯의 각 구성이 무엇을 의미하는지 간단하게 알아보자.
박스플롯의 구성
각 요소들을 설명하면 다음과 같다.

요소 설명
이상치(outlier) 최소값보다 작은데이터 또는 최대값보다 큰 데이터가 이상치에 해당한다
최대값(upper whisker) ‘중앙값 + 1.5 × IQR’보다 작은 데이터 중 가장 큰 값
최소값(lower whisker) ‘중앙값 - 1.5 × IQR’보다 큰 데이터 중 가장 작은 값
IQR(Inter Quartile Range) 제3사분위수 - 제1사분위수
실수 값 분포에서 1사분위수(Q1)와 3사분위수(Q3)를 뜻하고 이 3사분위수와 1사분위수의 차이(Q3 - Q1)를 IQR라고 한다.
중앙값 박스내부의 가로선, 용어 그대로 중앙값이다
whisker 상자의 상하로 뻗어있는 선




Plotly로 박스플롯 작성하기


1
2
3
4
5
6
7
8
9
10
11
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


df3 = pd.DataFrame(np.random.randint(0, 100, (100, 2)), columns=['A', 'B']) #임의로 수 생성

plt.figure(figsize=(8,7)) # 크기 지정
boxplot = df3.boxplot(column=['B']) # df3의 'B'컬럼을 박스플롯으로 생성
plt.yticks(np.arange(0,101,step=5)) # 박스플롯이 그려질 범위 지정
plt.show()
Output


위처럼 임의로 생성된 데이터프레임을 이용해 박스플롯을 만들 수 있다.




References

산점도 그리기
산점도 마커 모양
위키백과 - 산점도
위키백과 - 상자 수염 그림
박스플롯 및 요소 설명

파이썬(Python) 사용자 지정 함수

사용자 지정 함수란?


파이썬에서(다른프로그래밍 언어, 스크립트 언어에서도) 함수란, 소프르웨어에서 특정 동작을 수행하는 일정 코드부분을 의미한다.

하나의 큰 프로그램을 여러부분으로 나누어주기 때문에 같은 함수를 여러 상황에서 여러차례 호출할 수 있고, 일부분을 수정하기 쉽다는 장점을 지닌다.

파이썬에서는 미리 정의 되어있는 built in 함수(내장함수)가 있고. 또, 사용자가 필요에 의해 정의를 한 사용자 지정 함수가 존재한다.

파이썬에서의 함수 모형


파이썬 함수의 기본 모형

1
2
3
4
def 함수명() :
실행문
실행문
...

이와 같은 구조인데 함수를 정의하는 def뒤에 함수명이 오고 소괄호()를 붙인 다음 콜론:을 붙여주고, 다음줄에 원하는 실행문을 들여쓰기하여 사용하면 된다.

1
2
def func() :
print('python function')

위는 기본 모형을 응용하여 함수를 정의한 것이다. 이는 입력값도, 반환값도 없는 함수이며 값이 있는 함수에 대해서는 후술하겠다.

그러나 위 코드는 함수를 정의한 것이지 사용을 한 것이 아니다. 그렇기 때문에 함수를 사용하기 위해서는 함수의 사용법을 알아야 한다.

1
2
3
4
5
def func() :
print('python function')

#함수 호출
func()
Output
1
python function

func()함수는 입력값이 없기때문에 호출시에 입력값을 넣어주지 않고 괄호만 입력해 준다.



입력값만 있는 함수


1
2
3
4
5
6
def func2(a) :
print('입력한 문자는 ' + a + ' 입니다.')

func2("비행기")
func2("자동차")
func2("파이썬")
Output
1
2
3
입력한 문자는 비행기 입니다.
입력한 문자는 자동차 입니다.
입력한 문자는 파이썬 입니다.

func2()함수의 입력값이 a 에 입력되어 출력 된 것을 볼 수 있다.



리턴값만 있는 함수


1
2
3
4
def func3() :
return "12345"

print(func3())
Output
1
12345

func3()의 값이 리턴되어 print()를 통해 출력된 것을 알 수 있다.



입력,리턴값이 모두 있는 함수


1
2
3
4
def func4(a, b) :
return a + b

print(func4(10,20))
Output
1
30

a,b의 입력값을 더하는 함수에 10,20의 값을 주었더니 예상대로 30이 출력 되었다.



기본 인자 값


입력이 있는 함수를 여러 곳에 사용할 때 반복되는 값에 대해서는 기본적인 값을 지정할 수 있다.
기본값은 입력 = 값의 형태로 작성된다.

1
2
3
4
5
def func_b(a,b,c=5) :
return a*b+c

print(func_b(2,3,10))
print(func_b(2,3))
Output
1
2
16
11

출력에서처럼 기본값이 주어진 c 인자에 별다른 값을 넣지 않으면 기본값 5로 계산되어 10이들어간 결과보다 5가 낮아지게 된다.

이렇게 기본 인자를 줄 때는 주의 할 점이 한 가지 있는데 바로 인자의 순서에 맞게 넣어주어야 한다는 것과, 기본값과 입력값이 없으면 에러가 난다는 것이다.
다음 예시를 보자.

1
2
3
4
def func_b2(a,b=5,c) :
return a*b+c

print(func_b2(2,3))

위와 같이 값을 주게 된다면 어떨까?
b에 기본값이 있으니 a와 c에 각각 2와 3이 입력된다고 생각한 사람도 있을 것이다.
그러나 이 생각은 적어도 사용자 지정 함수에서는 옳지 않다.

이 코드가 불가능한 데에는 두 가지 이유가 있다.

첫 번째로는 a에는 2가 들어가는 것이 맞겠지만, b에 기본값이 있더라도 두 번째 입력값 자리에 3을 넣게 되는 순간 그 숫자는 b에 입력되기 때문에 결국엔 기본값이 없는 c는 어떠한 값도 입력받지 못하게 되기 때문이고,

두 번째 이유로는 c의 인자에 기본값이 없음에도 앞에 있는 b의 인자에 기본값이 있으므로 아예 성립할 수 없는 코드이다.
그러므로 기본값을 부여받은 인자는 항상 뒤에 배치해야 한다.



키워드 인자


키워드 인자는 함수를 정의할때 인자에 키워드를 부여하고 함수를 호출할 때 키워드=값의 형태로 넣어줄 수 있는 인자이다.
그냥 인자에 값을 넣어주는것과 뭐가 다르냐?라는 의문이 들 수도 있다.
다음 예시를 보자.

1
2
3
4
def score(kim=100, lee=100, park=100, choi=100) :
print('score = kim :', kim, 'lee :',lee, 'park :',park, 'choi :',choi)

score(park= 50)
Output
1
score = kim : 100 lee : 100 park : 50 choi : 100

이렇게 중간의 인자만 키워드=값의 형태로 입력해 값을 변경해 줄 수 있다.
예제처럼 여러 기본값이 있고 그중 몇 가지의 기본값만 바꿔 주어야 할 때 용이하게 쓸 수 있다.

Arbitrary Argument Lists (임의 인자 리스트)


Arbitrary Argument Lists는, 여러인자를 함수에 잔달하는 방법들중 하나이다.

함수내부에서 이 인자들은 튜플로 감싸져있으며 이는*argsarguments 생성자를 사용하여 정의 된다.

1
2
3
4
5
6
7
8
9
10
def avg_score(*numbers) :
s = 0
count = 0
for i in numbers:
s += i
count += 1
return s / count

print('국어와 수학점수의 평균은{}점 입니다'.format(avg_score(95, 87)))
print('입력된 숫자들의 평균은{} 입니다.'.format(avg_score(42,63,45,32,48)))
Output
1
2
국어와 수학점수의 평균은91.0점 입니다
입력된 숫자들의 평균은46.0 입니다.

위 코드에서는 *args*numbers로 대체했다.
이처럼 함수를 호출 할 때에 숫자를 몇가지를 넣어도 사용이 가능하다.



Lambda 함수


우리가 앞에서 배웠던 대로 사용자 지정 함수를 정의하고 사용하여 평균을 구하라고 한다면 아마 다음과 같을것이다.

1
2
3
4
5
def avg(x,y):
return(x + y) / 2
print(avg(5,13))

>> 9.0

그러나 파이썬은 Lambda함수를 통해서 이 코드를 더욱 짧게 줄일수 있다.

1
2
3
print((lambda x,y: (x + y)/2)(5,13))

>> 9.0

그러나 배우는 입장인 내 눈으로 단점을 찾아보자면 함수인데 정의를 하는 부분이 따로 없다 보니, 출력할 일이 여러 번 생긴다면 번거로워 질 것 같다.
그러니 앞으로 호출 횟수에 따라 적다면 람다 함수를, 많다면 기본적인 사용자 지정 함수를 사용하는 방식이 좋을 듯하다.



References

캐글 데이터 시각화 해석-1

임포트 및 데이터프레임 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
print(os.path.join(dirname, filename))

# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All"
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
1
2
from plotly.offline import plot, iplot, init_notebook_mode
init_notebook_mode(connected=True)
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from warnings import filterwarnings
filterwarnings('ignore')

colors = ['#B1EDED','#B1B2ED','#1DE7ED','#1DA5ED','#1D50ED','#16548E']

df = pd.read_csv('../input/kaggle-survey-2021/kaggle_survey_2021_responses.csv')
df.head()

원 그래프 해석


1
2
3
4
5
6
7
8
9
10
11
fig = go.Figure( data=[ # 그래프의 형태를 나타내는 함수
go.Pie( # 원그래프
labels = df['Q2'][1:].value_counts().index, # 값에 붙일 이름 - df['Q2'][1:].value_counts()의 인덱스
values = df['Q2'][1:].value_counts().values, # 나타낼 값 - df['Q2'][1:].value_counts()의 값
textinfo = 'label+percent')]) # 그래프 항목당 나타낼 텍스트 (여기서는 항목명, 비율)
fig.update_traces(
marker=dict(colors=colors[2:])) # 그래프를 어떤 색으로 표현할 것인지
fig.update_layout( # 그래프의 레이아웃 설정
title_text='Gender Distribution', # 그래프의 제목
showlegend=False) # 범례표시여부
fig.show()
그래프

원 그래프

코드 해석
1
2
3
4
5
6
fig = go.Figure(data=[
go.Pie(
labels = df['Q2'][1:].value_counts().index,
values = df['Q2'][1:].value_counts().values,
textinfo = 'label+percent'
)])

fig = go.Figure(data=[
-> 그래프의 기본적인 틀을 설정하는 함수이고, fig에 데이터를 부여해준다.

go.Pie(
-> 그래프의 형태가 파이모양(원그래프)임을 의미한다.

labels = df['Q2'][1:].value_counts().index
-> 그래프로 표현될 값에 붙일 이름이다. 이 코드에서는 ‘df’의 ‘Q2’열에 있는 데이터의 ‘1번인덱스(질문열을 제외하기 위함) 행부터 마지막까지’ 카운트하고 값에따라 분류했을 때의 인덱스열 인 것이다.

values = df['Q2'][1:].value_counts().values
-> 그래프로 표현될 값이다. 이 코드에서는 ‘df’의 ‘Q2’열에 있는 데이터의 ‘1번인덱스 행부터 마지막까지’ 카운트하고 값에따라 분류했을 때의 값(각 값을 카운트한 값) 이다.

textinfo = 'label+percent'
-> 그래프에 표시된 항목에 나타낼 텍스트를 설정한다. 이 코드에서는 항목명(label)과 비율(percent)을 나타낸다.


1
2
3
4
5
6
fig.update_traces( 
marker=dict(colors=colors[2:])) # 그래프를 어떤 색으로 표현할 것인가를 설정
fig.update_layout( # 그래프의 부가정보 설정
title_text='Gender Distribution', # 그래프 제목
showlegend=False) # 범례표시여부
fig.show()

fig.update_traces(
-> 추가바람

marker=dict(colors=colors[2:]))
-> 그래프의 색상을 설정한다. 이 코드에서는 위에서 설정된 colors 리스트에서 2번 인덱스부터 순서대로 사용한다.

fig.update_layout(
-> 그래프의 부가정보를 설정한다.

title_text='Gender Distribution'
-> 그래프의 제목을 설정한다.

showlegend=False)
-> 범례의 표기여부를 결정한다. 이 코드에서는 False이므로 범례가 표기되지 않는다.

fig.show()
-> 화면에 그래프를 표시하는 기능을한다. 몇몇에디터에서는 자동으로 표시되기때문에 호출할 필요가 없는 경우가 있다.

막대그래프 해석


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
man = df[df['Q2'] == 'Man']['Q1'].value_counts() # 성별이 남성[df['Q2'] == 'Man']인 행에서 나이['Q1']의 값을 카운트하여 시리즈로 만듦.
woman = df[df['Q2'] == 'Woman']['Q1'].value_counts() # 성별이 여성[df['Q2'] == 'Woman']인 행에서 나이['Q1']의 값을 카운트하여 시리즈로 만듦.
textonbar_man = [ # list comprehension = [(변수를 활용한 값) for (사용할 변수 이름) in (순회 할 수 있는 값)]
round((m/(m+w))*100, 1) for m, w in zip(man.values, woman.values)] # for문을 사용하여 round함수의 계산을 하고 textonbar_man에 저장
textonbar_woman = [ # list comprehension
round((w/(m+w))*100, 1) for m, w in zip(man.values, woman.values)]

# go = graph_objects
fig = go.Figure(data=[
go.Bar( # 막대그래프
name='Man', # 그래프로 나타낼 항목
x=man.index, # x축에 man의 인덱스
y=man.values, # y축에 man의 값
text=textonbar_man, # 막대의 값을 작성해줄 텍스트
marker_color=colors[2]), #막대 색
go.Bar(
name='Woman',
x=woman.index,
y=woman.values,
text=textonbar_woman,
marker_color=colors[3])
])
fig.update_traces(
texttemplate='%{text:.3s}%', # fig(print(fig)로 출력가능)내부의 text 인자를 차례대로 출력 (그래프의 위의 텍스트를 표현)
textposition='inside') # 그래프상에서 값의 위치
fig.update_layout(
barmode='stack', # 막대의 형태
title_text='Age distribution by gender', # 그래프 제목
xaxis_title='Age', # x축 제목
yaxis_title='Counts') # y축 제목
fig.show()
그래프

막대 그래프

코드 해석
1
2
3
4
man = df[df['Q2'] == 'Man']['Q1'].value_counts()
woman = df[df['Q2'] == 'Woman']['Q1'].value_counts()
textonbar_man = [ round((m/(m+w))*100, 1) for m, w in zip(man.values, woman.values)]
textonbar_woman = [ round((w/(m+w))*100, 1) for m, w in zip(man.values, woman.values)]

man = df[df['Q2'] == 'Man']['Q1'].value_counts()
-> 성별이 남성[df['Q2'] == 'Man]인 행에서 나이['Q1']의 값을 카운트하여 시리즈를 생성한다.

woman = df[df['Q2'] == 'Woman']['Q1'].value_counts()
-> 성별이 여성[df['Q2'] == 'Woman']인 행에서 나이['Q1']의 값을 카운트하여 시리즈를 생성한다.

textonbar_man = [round((m/(m+w))*100, 1) for m, w in zip(man.values, woman.values)]
-> for문을 사용하여 round함수를 계산 하고 textonbar_man에 저장한다.

textonbar_woman = [round((uw/(m+w))*100, 1) for m, w in zip(man.values, woman.values)]
-> for문을 사용하여 round함수를 계산 하고 textonbar_woman에 저장한다.



1
2
3
4
5
6
7
8
9
10
fig = go.Figure(data=[
go.Bar(
name='Man', x=man.index, y=man.values,
text=textonbar_man, marker_color=colors[2]
),
go.Bar(
name='Woman', x=woman.index, y=woman.values,
text=textonbar_woman, marker_color=colors[3]
)
])

go.Bar(
-> 그래프의 모양이 막대모양임을 의미한다.

name='Man', x=man.index, y=man.values,
-> 순서대로 막대의 이름, x축에는 man의 인덱스, y축에는 man의 값을 나타내라는 의미이다.

text=textonbar_man, marker_color=colors[2]),
-> 각각 막대의 값을 작성해줄 텍스트, 막대의 색을 의미한다.



1
2
3
4
5
6
7
8
9
fig.update_traces(
texttemplate='%{text:.3s}%',
textposition='inside')
fig.update_layout(
barmode='stack',
title_text='Age distribution by gender',
xaxis_title='Age', yaxis_title='Counts')
fig.show()
)

texttemplate='%{text:.3s}%',
-> fig(print(fig)로 출력가능)내부의 text 인자를 차례대로 출력 (그래프의 위의 텍스트를 표현)

textposition='inside'
-> 그래프상에서의 값의 위치를 설정한다.

barmode='stack'
-> 막대의 형태를 표현한다.

title_text='Age distribution by gender'
-> 그래프의 제목을 설정한다.

xaxis_title='Age', yaxis_title='Counts'
-> 그래프의 x축 제목, y축 제목

몇몇 요소 확인법


print(type(데이터))
-> 데이터의 타입을 출력한다

데이터.head(),데이터.tail()
-> 데이터를 인덱스 순으로 출력한다. head는 처음부터 끝까지, tail은 반대로 출력하며 괄호안에 숫자를 입력하면 숫자만큼 출력한다.

References

go.Figure() properties
update_traces() properties
update_layout() properties
show() properties
go.Bar() properties

NumPy 기본 다지기

Numpy란 무엇인가?

Numpy_Symbol
Numpy는 상당부분 C언어로 작성된 파이썬 라이브러리이다. 기본적으로 array라는 자료를 생성하고 이를 바탕으로 색인, 처리, 연산 등을 하는 기능을 수행한다. 물론 C언어로 작성되었기 때문에 속도도 꽤나 빠른편이다.

Numpy의 기본

Numpy 불러오기


Numpy를 사용하기 위해서는 먼저 임포트시켜줘야 한다.

1
import numpy as np

위처럼 입력하면 Numpy의 임포트가 된다. 뒤의 as np를 빼고 나머지만 입력해도 되지만, 앞으로 사용할 코드에서 조금 더 편히 사용하기 위하여(그리고 관례적으로) as np를 작성해 준다.

Numpy배열 생성 및 둘러보기


Numpy는 기본적으로 array라는 자료구조를 사용하기때문에 배열을 생성하는 방법에 대해 먼저 알아두어야 한다.

1
2
3
4
arr1 = [1,2,3]
my_array1 = np.array(arr1)
print(my_array1)
print(my_array1.shape)

Output:

[1 2 3]
(3,)

위의 출력 중 첫째줄은 arr1의 배열을 그대로 my_arrary1로 가져와 출력한 것이고, 둘째 줄은 가져온 배열의 길이를 튜플로 나타낸 것이다. 값 뒤에 콤마(,)가 붙어있는 이유는 값이 하나만 존재할 때, 튜플은 값 뒤에 콤마가 있어야 하기 때문이다.




다음은 2차원 배열일떄의 예제이다.

1
2
3
4
my_array3 = np.array([[2,4,6],[8,10,12],[14,16,18],[20,22,24]])
print(my_array3)
print(my_array3.shape)
print(my_array3.dtype)

Output:

[[ 2  4  6]
 [ 8 10 12]
 [14 16 18]
[20 22 24]]
(4, 3)
int64

먼저 세개의 출력 중 첫번째로 my_array3의 값인 리스트들이 차례로 나열되며, 그 다음으로는 배열의 (행, 열)의 수, 마지막으로 배열내의 요소의 데이터타입을 출력한다.




마지막으로 3차원 배열일때의 예제이다.

1
2
my_array5 = np.array([[[1, 2], [3, 4],[5, 6]], [[5, 6], [7, 8], [9, 10]]])
my_array5.shape

Output:

(2, 3, 2)

세려는 양(또는 각각) 배열의 수가 대칭일때의 예제이다, 가장 바깥쪽의 배열부터 순서대로 배열의 수를 출력한다.
그렇다면 대칭이 아니라면 어떻게 출력될까? 다음을 살펴보자

1
2
my_array5 = np.array([[[1, 2], [3, 4], [5, 6, 7]], [[5, 6], [7, 8], [9, 10]]])
my_array5.shape

Output:

(2, 3)

출력과 동시에 에러(위 출력창에서는 삭제함)가 뜨는데 추측하기론 양쪽 배열이 대칭이 아니기에 양 배열의 길이가 같은 두번째 항목까지는 출력되나 2와 3으로 갈리는 마지막 항목에서 출력이 안되는것 같다.
확실하지않으니 참고만…

Numpy의 기본 함수들


Numpy는 여러 함수들을 사용할수 있다, 하지만 함수의 종류가 너무 많기 때문에 이 챕터에서는 기본적인 함수들만 알아보도록 한다.

  • arange


arange는 배열을 만들어주는 함수이다.
arange([시작],끝,[만큼 건너뜀])으로 작성 할 수 있으며 []안의 항목은 생략 할 수 있다.

1
2
arrange_array = np.arange(3, 13, 2)
arrange_array

Output:

array([ 3,  5,  7,  9, 11])

3부터 시작해서 12(13-1)까지 출력하며 2씩 건너뛰는 배열을 생성하는 arange예제이다.

  • zeros, ones


zerosones는 0또는 1로 초기화된 shape* 차원의 ndarray** 배열 객체를 반환한다.
두 함수 모두 객체 생성시 데이터 타입은 float64형식이다.



*shape : 행열의 차원
**ndarray : N차원의 배열객체. 기존파이썬과는 다르게 ndarray는 오직 같은 종류의 데이터만을 배열에 담을 수 있다.

1
2
3
4
zeros_array = np.zeros((3,2))
print(zeros_array)
print("Data Type is:", zeros_array.dtype)
print("Data Shape is:", zeros_array.shape)

Output:

[[0. 0.]
 [0. 0.]
 [0. 0.]]
Data Type is: float64
Data Shape is: (3, 2)

순서대로 배열, 데이터 타입, 데이터의 차원을 출력한다.


1
2
3
4
ones_array = np.ones((3,4), dtype='int32')
print(ones_array)
print("Data Type is:", ones_array.dtype)
print("Data Shape is:", ones_array.shape)

Output:

[[1 1 1 1]
 [1 1 1 1]
 [1 1 1 1]]
Data Type is: int32
Data Shape is: (3, 4)

같은 순서로 항목들을 출력했고 배열생성시 데이터 타입을 바꿀수 있음을 보여주는 예제이다.

  • reshape


reshape는 구조를 재배열해주는 함수이다. 배열명.reshape(차원, 차원)으로 사용할 수 있다.

1
2
3
4
# 위에서 만들어진 3 x 4 배열의 ones_array를 reshape하여 2 x 6로 재배열
after_reshape = ones_array.reshape(2,6)
print(after_reshape)
print("Data Shape is:", after_reshape.shape)

Output:

[[1 1 1 1 1 1]
 [1 1 1 1 1 1]]
Data Shape is: (2, 6)

reshape를 통해서 3x4 배열을 2x6으로 재배열 해준 가장 기본적인 예제이다.

재배열하려는 배열이 3x4 라면 3x4를 곱해서 나오는 값인 12의 인수들로 12의 결과가 나오는 배열((1,12), (2,6), (4,3))들로 바꿀 수 있으며, (2,2,3)등과 같은 3차원배열로도 재배열이 가능하다.

  • reshape의 값에 -1을 넣는다면?


그렇다면 reshape의 괄호 차원값에 -1을 넣는다면 어떻게될까?
다음 결과를 보자.

1
2
after_reshape2= ones_array.reshape(-1,6)
print(after_reshape2)

Output:

[[1 1 1 1 1 1]
 [1 1 1 1 1 1]]

-1을 작성한 곳에 12에서 나머지(두번째 값인 6)값을 보고 첫번째 값은 알아서 2로 지정이 된 것이다.



다음은 값이 -1 하나일 때의 예제이다.

1
2
after_reshape2= ones_array.reshape(-1)
print(after_reshape2)

Output:

[1 1 1 1 1 1 1 1 1 1 1 1]

결과와 같이 1차원 배열로 바뀐다. 하지만 (12)일뿐, 2차원 배열인 (1,12)과는 같지 않다.

Numpy 인덱싱과 슬라이딩


Numpy의 배열에도 값을 추출 할 수 있게 인덱싱과 슬라이딩이 가능하다.

1
2
3
4
my_array2 = np.arange(start=3,stop=30,step=3)
my_array2 = my_array2.reshape(3,3)

my_array2[1:3,:]

Output:

array([[12, 15, 18],
        [21, 24, 27]])

출력에서 첫번째 인자는 1에서 2(3-1)번째 까지의 배열을 출력하고, 두번째 인자인 :은 첫번째 인자에서 지목된 배열의 항목을 모두 출력하는 것이다.

Numpy 정렬


여러 값이 모여있는 array인 만큼 정렬도 가능하다. 이 챕터에서는 오름,내림차순으로 정렬해주는 sort(), 값이 낮은 순서대로 인덱스를 배정해 배열을 출력해주는 argsort()가 있다.

  • sort()


1
2
3
4
5
height_arr = np.array([174, 165, 180, 182, 168])
sorted_height_arr = np.sort(height_arr)

print('Height Matrix: ', height_arr)
print('np.sort() Matrix: ', sorted_height_arr)

Output:

Height Matrix:  [174 165 180 182 168]
np.sort() Matrix:  [165 168 174 180 182]

결과에서 보이다시피 sort()함수는 배열내의 값을 오름차순으로 정렬해준다.

내림차순으로 정렬을 하고 싶다면 다음과 같이 하면 된다.

1
2
desc_sorted_height_arr = np.sort(height_arr)[::-1]
print('np.sort()[::-1] : ', desc_sorted_height_arr)

Output:

np.sort()[::-1] :  [182 180 174 168 165]

위처럼 정렬을 할 때 sort()의 뒷부분에 [::-1]을 붙여주면 된다.

  • argsort()


1
2
3
4
5
6
fives = np.array([10, 5, 15, 20])
fives_order = fives.argsort()

print("The original data", fives)
print("The argsort(): ", fives_order)
print("The asending:", fives[fives_order])

Output:

The original data [10 5 15 20]
The argsort():  [1 0 2 3]
The asending: [ 5 10 15 20]

출력의 첫번째 줄은 가장 처음 입력했던 일반적인 배열이다.
두번째 줄은 오름차순으로 인덱스를 매긴 배열이며,
마지막은 두번째줄의 배열에 따라 첫번째줄의 결과인 배열을 정렬한 것이다.

마크다운(Markdown) 문법

지금 당장만 해도 이 글을 마크다운으로 작성하고 있는 나는 HTML를 접해보긴 했지만 자유자재로 쓸 수 있는정도는 아니였기에 깃허브 블로그를 시작하면서 마크다운의 문법에 대해 알아야 할 필요가 생겼다.

다른 포스트들도 마찬가지지만 더욱 이 포스트는 자주 찾아 봐야 할 것 같기에 문법만을 기록하며, 접기를 최대한 지양한다.

각 챕터의 위쪽은 코드 그 아래는 출력이다.

마크다운 문법


제목 작성

1
2
3
4
# 이러면 큰제목 <h1>태그
## 이러면 중간제목 <h2>태그
### 이러면 작은제목 <h3>태그
#### 이것도 되긴 하지만 굵게한 글자와 차이가 없음. <h4>태그로 사용된다

이러면 큰제목 <h1>태그

이러면 중간제목 <h2>태그

이러면 작은제목 <h3>태그

이것도 되긴 하지만 굵게한 글자와 차이가 없는 <h4>태그로 사용된다


줄바꿈

1
2
줄바꿈은 행의 끝에서 공백 두칸을 주고  
다음행에 작성하면 된다.

줄바꿈은 행의 끝에서 공백 두칸을 주고
다음행에 작성하면 된다.


코드블럭

1
2
3
```과 ~~~는 마크다운의 내용을 코드블럭을 씌운다.
```(언어명) 내용 ``` 의 형태로 작성하며
이것도 코드블럭으로 씌워진 것이다.

인라인코드

1
이것은 `인라인코드`이다.

이것은 인라인코드이다.


링크 걸기

www.naver.com
그냥 주소를 써도 링크로 클릭이 되지만 ,

1
[WJ 블로그](cincu4221.github.io)

WJ 블로그
위처럼 작성하면 주소를 숨기고 텍스트에 링크를 걸 수 있다.


텍스트

1
**강조된 텍스트**

강조된 텍스트


1
2
*기울인텍스트*
***기울임,강조를적용한텍스트***

기울인텍스트
기울임,강조를적용한텍스트


1
~~취소선입니다~~

취소선입니다



글자색

1
2
3
4
5
6
7
8
<span style="color:orange">주황색 글씨</span>  
<span style="color:yellow">노란색 글씨</span>
<span style="color:#FF0000">빨간색 글씨</span>
<span style="color:blue">파란색 글씨</span>
<span style="color:green">초록색 글씨</span>
<span style="color:pink">분홍색 글씨</span>

<span style="color:#00FFFF">헥스코드 적용 글씨</span>

주황색 글씨
노란색 글씨
빨간색 글씨
파란색 글씨
초록색 글씨
분홍색 글씨

헥스코드 적용 글씨

검색하기 애매한 색도 여기 에서 찾을 수 있다.


구분선

1
2
3
***
-- --
---







표만들기

1
2
3
4
|제목|제목|
|:---:|:---:|
|내용|내용|
|||
제목 제목
내용 내용
내용 내용





리스트

1
2
3
4
5
6
7
8
9
10
11
12
1. 순서 있는 리스트
2. 순서 있는 리스트
345. 순서 있는 리스트 (순서가 틀려도 상관 없다)

* 순서 없는 리스트
* 순서 없는 리스트

+ 순서 없는 리스트
+ 순서 없는 리스트

- 순서 없는 리스트
- 순서 없는 리스트
  1. 순서 있는 리스트
  2. 순서 있는 리스트
  3. 순서 있는 리스트 (순서가 틀려도 상관 없다)
  • 순서 없는 리스트
  • 순서 없는 리스트
  • 순서 없는 리스트
  • 순서 없는 리스트
  • 순서 없는 리스트
  • 순서 없는 리스트

앞으로 계속 추가할것

결정 나무(Decision Tree) 간단 설명

결정 나무란?


결정 나무 Decision Tree 는 분류와 회귀 문제에 널리 사용하는 데이터마이닝 기법이다. 결정 나무는 결정을 하기위해 예/아니오 질문을 연속해가며 학습한다.

결정나무 간단설명영상
결정나무 사이킷런 튜토리얼

결정나무의 의사결정 과정


결정 나무가 행하는 이 과정은 ‘스무고개’를 할때의 그것과 비슷하다.
사과, 포도, 멜론, 녹차를 구분한다고 생각해보자. 사과와 포도는 과일이고 멜론과 녹차는 과일이 아니다.
‘과일인가요?’라는 질문을 통해 사과, 포도 / 멜론, 녹차를 나눌 수 있고, 사과와 포도는 ‘(과실 전체의)모양이 둥근가요?’, 멜론과 녹차는 ‘넝쿨에서 자라나요?’ 라는 질문을 통해 분류해 낼 수 있다.
위의 결정나무를 도식화하면 아래와 같다.

도식화한 결정나무

이렇게 질문에 따라 데이터를 구분짓는 모델을 결정나무모델이라고 한다. 한번의 질문에 True 혹은 False를 통해 변수영역을 두 개로 분기한다.

모양이 나무를 뒤집어 놓은것 같아서 Decision Tree 이다.

위의 그림에서 각각의 네모상자를 노드Node라고 하며, 가장 처음의 분기점을 Root Node라고 하고, 가장 마지막 노드를 Leaf Node또는 Terminal Node라고 한다.

결정나무분류기 = DecisionTreeClassifier


DecisionTreeClassifier()는 결정나무의 기능을 바꿀수 있는 파라미터인데 파라미터 내부의 특성 하나하나를 하이퍼파라미터라고 한다.


DecisionTreeClassifier()파라미터의 괄호 안에 각각의 값을 입력할 수 있는데 다음과 같은 항목들이 있다.

하이퍼파라미터 기능
criterion 분할 품질을 측정하는 기능 (default : gini)
splitter 각 노드에서 분할을 선택하는 데 사용되는 전략 (default : best)
max_depth 트리의 최대 깊이 (값이 클수록 모델의 복잡도가 올라간다.)
min_samples_split 자식 노드를 분할하는데 필요한 최소 샘플 수 (default : 2)
min_samples_leaf 리프 노드에 있어야 할 최소 샘플 수 (default : 1)
min_weight_fraction_leaf min_sample_leaf와 같지만 가중치가 부여된 샘플 수에서의 비율
max_features 각 노드에서 분할에 사용할 특징의 최대 수
random_state 난수 seed 설정
max_leaf_nodes 리프 노드의 최대수
min_impurity_decrease 최소 불순도
min_impurity_split 나무 성장을 멈추기 위한 임계치
class_weight 클래스 가중치
presort 데이터 정렬 필요 여부

괄호 내부에 아무것도 입력하지않으면 기본값으로 결정나무가 출력된다.



References

파이썬 시각화 기본

파이썬 시각화의 기본 형태들


  • 선 그래프로 시각화하기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import matplotlib.pyplot as plt

    dates = [
    '2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05',
    '2021-01-06', '2021-01-07', '2021-01-08', '2021-01-09', '2021-01-10'
    ]
    min_temperature = [20.7, 17.9, 18.8, 14.6, 15.8, 15.8, 15.8, 17.4, 21.8, 20.0]
    max_temperature = [34.7, 28.9, 31.8, 25.6, 28.8, 21.8, 22.8, 28.4, 30.8, 32.0]

    fig, ax = plt.subplots()
    ax.plot(dates, min_temperature, label = "Min Temp")
    ax.plot(dates, max_temperature, label = "Max Temp")
    ax.legend()
    plt.show()
Output

선 그래프로 시각화

  • 위의 그래프에서 크기의 변화를 준 그래프
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import matplotlib.pyplot as plt

    dates = [
    '2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05',
    '2021-01-06', '2021-01-07', '2021-01-08', '2021-01-09', '2021-01-10'
    ]
    min_temperature = [20.7, 17.9, 18.8, 14.6, 15.8, 15.8, 15.8, 17.4, 21.8, 20.0]
    max_temperature = [34.7, 28.9, 31.8, 25.6, 28.8, 21.8, 22.8, 28.4, 30.8, 32.0]

    fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10,6))
    axes.plot(dates, min_temperature, label = 'Min Temperature')
    axes.plot(dates, max_temperature, label = 'Max Temperature')
    axes.legend()
    plt.show()
Output

크기의 변화를 준 그래프

  • figaxes 출력
    1
    2
    print(fig)
    print(axes)
Output
Figure(720x432)
AxesSubplot(0.125,0.125;0.775x0.755)

Matplotlib


선 그래프

먼저 yfinance라이브러리를 사용하기 위해 설치를 한다.

1
!pip install yfinance --upgrade --no-cache-dir
실행시
Collecting yfinance
  Downloading yfinance-0.1.64.tar.gz (26 kB)
Requirement already satisfied: pandas>=0.24 in /usr/local/lib/python3.7/dist-packages (from yfinance) (1.1.5)
Requirement already satisfied: numpy>=1.15 in /usr/local/lib/python3.7/dist-packages (from yfinance) (1.19.5)
Requirement already satisfied: requests>=2.20 in /usr/local/lib/python3.7/dist-packages (from yfinance) (2.23.0)
Requirement already satisfied: multitasking>=0.0.7 in /usr/local/lib/python3.7/dist-packages (from yfinance) (0.0.9)
Collecting lxml>=4.5.1
  Downloading lxml-4.6.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl (6.3 MB)
     |████████████████████████████████| 6.3 MB 5.3 MB/s 
[?25hRequirement already satisfied: python-dateutil>=2.7.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24->yfinance) (2.8.2)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24->yfinance) (2018.9)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.7/dist-packages (from python-dateutil>=2.7.3->pandas>=0.24->yfinance) (1.15.0)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests>=2.20->yfinance) (1.24.3)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests>=2.20->yfinance) (2021.5.30)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests>=2.20->yfinance) (2.10)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests>=2.20->yfinance) (3.0.4)
Building wheels for collected packages: yfinance
  Building wheel for yfinance (setup.py) ... [?25l[?25hdone
  Created wheel for yfinance: filename=yfinance-0.1.64-py2.py3-none-any.whl size=24109 sha256=da9039df457bcaed01c34fcce5bc8ee52dcf33151b9275684543166937fa1286
  Stored in directory: /tmp/pip-ephem-wheel-cache-qozcsm2m/wheels/86/fe/9b/a4d3d78796b699e37065e5b6c27b75cff448ddb8b24943c288
Successfully built yfinance
Installing collected packages: lxml, yfinance
  Attempting uninstall: lxml
    Found existing installation: lxml 4.2.6
    Uninstalling lxml-4.2.6:
      Successfully uninstalled lxml-4.2.6
Successfully installed lxml-4.6.4 yfinance-0.1.64

다음과 같이 출력되며 yfinace를 설치한다.

yfinance를 임포트해주고 그로부터 데이터를 받아와 출력을 할수 있다.

1
2
3
import yfinance as yf
data = yf.download('AAPL', '2019-08-01', '2020-08-01')
data.info()
Output
[*********************100%***********************]  1 of 1 completed
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 253 entries, 2019-08-01 to 2020-07-31
Data columns (total 6 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   Open       253 non-null    float64
 1   High       253 non-null    float64
 2   Low        253 non-null    float64
 3   Close      253 non-null    float64
 4   Adj Close  253 non-null    float64
 5   Volume     253 non-null    int64  
dtypes: float64(5), int64(1)
memory usage: 13.8 KB

다음과 같이 애플의 1년동안의 주가를 볼 수 있다.

데이터의 컬럼을 지목해서 열람하는것 역시 가능하다.

1
2
ts = data['Open']
print(ts.head())
Output
Date
2019-08-01    53.474998
2019-08-02    51.382500
2019-08-05    49.497501
2019-08-06    49.077499
2019-08-07    48.852501
Name: Open, dtype: float64

data에 담겨있는 애플의 주가정보 중 ‘Open’에 해당하는 전일 종가를 가장 앞쪽(.head())부터 출력한 것이다.
애플주식이 이렇게 쌌었나 검색해보니 이게 맞다….



방법 1. Pyplot API


1
2
3
4
5
6
7
8
9
10
11
12
13
# import fix_yahoo_finance as yf
import yfinance as yf
import matplotlib.pyplot as plt

data = yf.download('AAPL', '2019-11-01', '2021-11-01')
ts = data['Open']
plt.figure(figsize=(10,6))
plt.plot(ts)
plt.legend(labels=['Price'], loc='best')
plt.title('Stock Market fluctuation of AAPL')
plt.xlabel('Date')
plt.ylabel('Stock Market Open Price')
plt.show()
Output
[*********************100%***********************]  1 of 1 completed

애플의 최근 2년간 전일종가 그래프
이처럼 결과가 출력되지만 이 문법은 시각화를 처음배우는 초심자에게는 적합하지 않다고 한다.
후술할 문법과 위 문법 모두 출력은 되나 이 문법은 객체지향이 아니기도 하고 상대적으로 복잡하기때문에 초심자의 경우에 헷갈릴수 있어 사용하지 않는다.
구글링 했을때 객체.이 아닌 plt.으로 시작하는 애들이 있다면 그 코드는 스킵하는게 좋다.



방법 2. 객체지향 API


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

fig = Figure()

import numpy as np
np.random.seed(6)
x = np.random.randn(20000)

ax = fig.add_subplot(111)
ax.hist(x, 100)
ax.set_title('Artist Layer Histogram')
# fig.savefig('Matplotlib_histogram.png')
plt.show()

이 방법에 대해서는 따로 언급이 없었기 때문에 바로 방법 3으로 넘어간다.



방법 3. Pyplot API + 객체지향 API


1
2
3
4
5
6
7
8
9
10
11
12
13
import yfinance as yf
import matplotlib.pyplot as plt

data = yf.download('AAPL', '2019-08-01', '2020-08-01')
ts = data['Open']

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(ts)
ax.set_title('Stock Market fluctuation of AAPL')
ax.legend(labels=['Price'], loc='best')
ax.set_xlabel('Date')
ax.set_ylabel('Stock Market Open Price')
plt.show()
Output
[*********************100%***********************]  1 of 1 completed


드디어 꼭 외우라고 하셨던 pyplot + 객체지향 API 방법이다.
특히 7번째 행 부터 마지막까지가 중요한데 그에대한 설명은 아래에 표로 적겠다.
중요하다 몇번을 강조하셨으니 위 코드는 변형을 해가며 여러번 작성해보자.

설명 표
코드 설명
fig, ax = plt.subplots() 데이터 전체적 외형을 설정하는 부분
ax.plot(ts) 데이터를 표현해주는 행
ax.set_title() 데이터 시각화의 제목
ax.legend() 범례
ax.set_xlabel() x축 데이터의 제목
ax.set_ylabel() y축 데이터의 제목
plt.show() 안해도 상관없으나 ‘완료후 게시’ 라는 뜻으로 작성
앞으로 나올 표의 내용도 표의 위에 있는 코드들과 적절히 섞어서 이해하길 바란다.

막대 그래프


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt
import numpy as np
import calendar

month_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
sold_list = [300, 400, 550, 900, 600, 960, 900, 910, 800, 700, 550, 450]

fig, ax = plt.subplots(figsize=(10,6))
plt.xticks(month_list, calendar.month_name[1:13], rotation=90)
plot = ax.bar(month_list, sold_list)
for rect in plot:
print("graph:", rect)
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.002*height,'%d' %
int(height), ha='center', va='bottom')

plt.show()
Output
graph: Rectangle(xy=(0.6, 0), width=0.8, height=300, angle=0)
graph: Rectangle(xy=(1.6, 0), width=0.8, height=400, angle=0)
graph: Rectangle(xy=(2.6, 0), width=0.8, height=550, angle=0)
graph: Rectangle(xy=(3.6, 0), width=0.8, height=900, angle=0)
graph: Rectangle(xy=(4.6, 0), width=0.8, height=600, angle=0)
graph: Rectangle(xy=(5.6, 0), width=0.8, height=960, angle=0)
graph: Rectangle(xy=(6.6, 0), width=0.8, height=900, angle=0)
graph: Rectangle(xy=(7.6, 0), width=0.8, height=910, angle=0)
graph: Rectangle(xy=(8.6, 0), width=0.8, height=800, angle=0)
graph: Rectangle(xy=(9.6, 0), width=0.8, height=700, angle=0)
graph: Rectangle(xy=(10.6, 0), width=0.8, height=550, angle=0)
graph: Rectangle(xy=(11.6, 0), width=0.8, height=450, angle=0)

막대 그래프로 시각화

메소드 설명

.xticks()는 x축의 눈금을 나타내는 메소드인데 기본적으로는 list자료형 한개을 사용한다.
하지만 메소드에 인자가 ‘list’ 두 개로 받아졌을 경우,
첫번째 list는 x축 눈금의 갯수가 된다.
두번째 list는 x축 눈금의 이름이 된다.
이 코드에서는 rotation 옵션도 들어가 있는데 이것은 그냥 이름을 몇도정도 기울일지 나타낸다.



plot = ax.bar()는 그래프를 막대로 만든다.
첫번째 리스트 인자의 수 만큼 막대가 생성되고,
두번째 리스트 인자의 값 만큼 막대가 길어진다.
이렇다보니 첫번째 리스트와 두번째 리스트의 인자의 수가 일치해야 에러가 나지 않는다.



for문 내부의 ax.text()Seaborn-막대그래프-표현할 값이 한 개인 막대 그래프 챕터에 서술했으니 참고하길 바란다.

산점도 그래프


  • 두개의 연속형 변수 (키, 몸무게 등)
  • 상관관계 != 인과관계


  • 나타내는 값이 한가지인 산점도 그래프
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import matplotlib.pyplot as plt
import seaborn as sns

# 내장 데이터
tips = sns.load_dataset("tips")
x = tips['total_bill']
y = tips['tip']

fig, ax = plt.subplots(figsize=(10, 6))
ax.scatter(x, y) # 각각의 값을 선으로 표현해주는 scatter()
ax.set_xlabel('Total Bill')
ax.set_ylabel('Tip')
ax.set_title('Tip ~ Total Bill')

fig.show()
Output

전체 값 대비 팁


  • 나타내는 값이 두 가지인 산점도 그래프
1
2
3
4
5
6
7
8
9
10
11
12
13
label, data = tips.groupby('sex')
tips['sex_color'] = tips['sex'].map({"Female" : "#0000FF", "Male" : "#00FF00"})

fig, ax = plt.subplots(figsize=(10, 6))
for label, data in tips.groupby('sex'):
ax.scatter(data['total_bill'], data['tip'], label=label,
color=data['sex_color'], alpha=0.5)
ax.set_xlabel('Total Bill')
ax.set_ylabel('Tip')
ax.set_title('Tip ~ Total Bill by Gender')

ax.legend()
fig.show()
Output

전체 값 대비 팁의 성별분포

히스토그램


  • 수치형 변수 1개
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

# 내장 데이터
titanic = sns.load_dataset('titanic')
age = titanic['age']

nbins = 21
fig, ax = plt.subplots(figsize=(10, 6))
ax.hist(age, bins = nbins) # 여기서 bins = nbins는 히스토그램을 더 세밀하게 나누어 준다.
ax.set_xlabel("Age")
ax.set_ylabel("Frequency")
ax.set_title("Distribution of Aae in Titanic")
ax.axvline(x = age.mean(), linewidth = 2, color = 'r')
fig.show()
Output

타이타닉호 탑승객의 나이 분포

코드 설명
.hist() 데이터를 히스토그램으로 표현해주는 메소드
.axvline() 데이터의 평균을 선으로 나타내주는 메소드

박스플롯


  • x축 변수: 범주형 변수, 그룹과 관련있는 변수, 문자열
  • y축 변수: 수치형 변수
1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import seaborn as sns

iris = sns.load_dataset('iris')

data = [iris[iris['species']=="setosa"]['petal_width'],
iris[iris['species']=="versicolor"]['petal_width'],
iris[iris['species']=="virginica"]['petal_width']]

fig, ax = plt.subplots(figsize=(10, 6))
ax.boxplot(data, labels=['setosa', 'versicolor', 'virginica'])

fig.show()
Output

png
수정바람) 정확히 어떻게 이 그래프가 출력되는지 모르기에 좀 더 공부후 수정할 것

히트맵


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

# 내장 데이터
flights = sns.load_dataset("flights")
flights = flights.pivot("month", "year", "passengers")

fig, ax = plt.subplots(figsize=(12, 6))
im = ax.imshow(flights, cmap = 'YlGnBu')
ax.set_xticklabels(flights.columns, rotation = 20)
ax.set_yticklabels(flights.index, rotation = 10)
fig.colorbar(im)

fig.show()
Output
     year month  passengers
0    1949   Jan         112
1    1949   Feb         118
2    1949   Mar         132
3    1949   Apr         129
4    1949   May         121
..    ...   ...         ...
139  1960   Aug         606
140  1960   Sep         508
141  1960   Oct         461
142  1960   Nov         390
143  1960   Dec         432

[144 rows x 3 columns]

연,월별 승객의 수

제목 제목
fig.colorbar() 값의 빈도 수에 대한 컬러바생성

Seaborn


산점도와 회귀선이 있는 산점도


  • 산점도
1
2
3
4
5
6
7
8
%matplotlib inline 

import matplotlib.pyplot as plt
import seaborn as sns

tips = sns.load_dataset("tips")
sns.scatterplot(x = "total_bill", y = "tip", data = tips)
plt.show()
Output

산점도


  • 회귀선이 있는 산점도
1
2
3
4
5
6
7
8
9
10
11
12
13
14
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize=(15, 5))
sns.regplot(x = "total_bill",
y = "tip",
data = tips,
ax = ax[0],
fit_reg = True)

sns.regplot(x = "total_bill",
y = "tip",
data = tips,
ax = ax[1],
fit_reg = False)

plt.show()
Output

회귀선이 있는 산점도
위의 코드처럼 fit_reg = True로 해줄 경우 회귀선이 나타나는것을 알 수 있다.
그리고 ax = ax[num]의 경우에는 그래프의 인덱스로 보인다.

히스토그램/커널 밀도 그래프


1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt
import seaborn as sns

tips = sns.load_dataset("tips")

plt.figure(figsize=(10, 6))
sns.displot(x = "tip", data = tips)
sns.displot(x="tip", kind="kde", data=tips) # 종류 = 커널밀도 그래프(kde)
sns.displot(x="tip", kde=True, data=tips) # 히스토그램에 kde를 넣을건가 = True
plt.show()
Output
<Figure size 720x432 with 0 Axes>

히스토그램
커널 밀도 그래프
커널 밀드 그래프가 그려진 히스토그램

박스플롯

1
2
3
4
5
6
7
8
#import matplotlib.pyplot as plt  # 주석처리된 부분은 원래 실행 해줘야 하는 내용이지만 위 히스토그램 챕터에서 미리 입력했기 때문에 생략한다. 
#import seaborn as sns

#tips = sns.load_dataset("tips")

sns.boxplot(x = "day", y = "total_bill", data = tips)
sns.swarmplot(x = "day", y = "total_bill", data = tips, alpha = .25)
plt.show()
Output

박스플롯

막대 그래프

1
2
3
4
5
6
7
#import matplotlib.pyplot as plt  # 이 주석 역시 원래 실행 해줘야 하는 내용이지만 위 히스토그램 챕터에서 미리 입력했기 때문에 생략한다. 이하 기본주석이라 하고 생략한다.
#import seaborn as sns

#tips = sns.load_dataset("tips")

sns.countplot(x = "day", data = tips)
plt.show()
Output

png


'tips'Data의 'day'값, 인덱스별 정렬, 'tips'의 내림차순 재배치
1
2
3
print(tips['day'].value_counts())
print("index: ", tips['day'].value_counts().index)
print("values: ", tips['day'].value_counts().values)
Sat     87
Sun     76
Thur    62
Fri     19
Name: day, dtype: int64
index:  CategoricalIndex(['Sat', 'Sun', 'Thur', 'Fri'], categories=['Thur', 'Fri', 'Sat', 'Sun'], ordered=False, dtype='category')
values:  [87 76 62 19]

'tips'Data의 'day'값에 대한 오름차순(ascending) 정렬
1
print(tips['day'].value_counts(ascending=True))
Fri     19
Thur    62
Sun     76
Sat     87
Name: day, dtype: int64

  • 표현할 값이 한 개인 막대 그래프
1
2
3
4
5
6
7
# 기본주석 생략
ax = sns.countplot(x = "day", data = tips, order = tips['day'].value_counts().index) # x축을 'day'로 지정, data는 'tips'로 채워넣음, 'day'의 값이 높은 순서대로 막대그래프 정렬
for p in ax.patches: # ax.patches = p
height = p.get_height() # 아래행을 실행하기위해 막대그래프의 높이 가져옴
ax.text(p.get_x() + p.get_width()/2., height+3, height, ha = 'center', size=9) # 막대그래프 위 수치 작성
ax.set_ylim(-5, 100) # y축 최소, 최대범위
plt.show()
Output

나타낼 값이 한 개인 막대그래프
나중에 다시 본다면 조금 설명이 필요할 것 같다.
특히 ax.text행의 인자가 조금 많은데 설명이 필요한 듯하다.
직접 colab에서 이것저것 만져본 결과 추측하기로는 다음 표과 같은듯 하다.

코드 설명
p.get_x() + p.get_width()/2. 수치가 들어갈 x축 위지
height+3 y축 위치(현재 +3)
height 수치의 값을 조절할 것인지(현재 +0)
ha = ‘center’ 수치를 (x,y)축의 가운데로 정렬
size=9 폰트의 크기이다

여기서 혹시나 ha = 'center'부분이 잘 이해가 안될수 있다.내가그랬다
ha =는 (x,y)축의 기준이 될 곳을 정하는 인자인듯 하다.
center말고도 left,right등을 사용할수 있는데 막대의 기준에서 왼쪽,오른쪽이 아닌 텍스트의 기준에서 왼쪽,오른쪽이라 방향을 선택하면 오히려 반대로 배치되는것을 알 수 있다.

  • 표현할 값이 두 개인 막대 그래프
1
2
3
4
5
6
7
8
9
# 기본주석 생략
ax = sns.countplot(x = "day", data = tips, hue = "sex", dodge = True,
order = tips['day'].value_counts().index)
for p in ax.patches:
height = p.get_height()
ax.text(p.get_x() + p.get_width()/2., height+3, height, ha = 'center', size=9)
ax.set_ylim(-5, 100)

plt.show()
Output

나타낼 값이 두 개인 막대그래프

이 코드에서 첫째줄의 인자를 표로 나타내면

코드 설명
x = “day” x축이 나타낼 자료
data = tips 표현할 데이터셋
hue = “sex” 그래프로 표현할 항목
dodge = True 항목끼리 나눠서 표현할 것인지
order = tips[‘day’].value_counts().index ‘day’의 값이 높은 순서대로 그래프 정렬

sns.countplot() x축이 나타낼 자료, 나타낼 데이터셋, 그래프로 나타낼 항목, 항목끼리 나눠서 표현할것인지, ‘day’의 값이 높은 순서대로 막대그래프 정렬

상관관계 그래프


데이터 불러오기 및 행, 열 갯수 표시하기
1
2
3
4
5
6
7
8
9
10
import pandas as pd 
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

mpg = sns.load_dataset("mpg")
print(mpg.shape) # 398 행, 9개 열

num_mpg = mpg.select_dtypes(include = np.number) # num_mpg에 'mpg' 데이터셋의 데이터타입 총갯수를 입력한다(숫자형 데이터타입만 포함)
print(num_mpg.shape) # 398 행, 7개 열 (두개가 사라진 이유는 number타입이 아닌 Object타입이기 때문)
(398, 9)
(398, 7)

데이터셋의 컬럼 표시
1
num_mpg.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 398 entries, 0 to 397
Data columns (total 7 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   mpg           398 non-null    float64
 1   cylinders     398 non-null    int64  
 2   displacement  398 non-null    float64
 3   horsepower    392 non-null    float64
 4   weight        398 non-null    int64  
 5   acceleration  398 non-null    float64
 6   model_year    398 non-null    int64  
dtypes: float64(4), int64(3)
memory usage: 21.9 KB

데이터셋 컬럼간의 상관관계 표시
1
num_mpg.corr()

mpg cylinders displacement horsepower weight acceleration model_year
mpg 1.000000 -0.775396 -0.804203 -0.778427 -0.831741 0.420289 0.579267
cylinders -0.775396 1.000000 0.950721 0.842983 0.896017 -0.505419 -0.348746
displacement -0.804203 0.950721 1.000000 0.897257 0.932824 -0.543684 -0.370164
horsepower -0.778427 0.842983 0.897257 1.000000 0.864538 -0.689196 -0.416361
weight -0.831741 0.896017 0.932824 0.864538 1.000000 -0.417457 -0.306564
acceleration 0.420289 -0.505419 -0.543684 -0.689196 -0.417457 1.000000 0.288137
model_year 0.579267 -0.348746 -0.370164 -0.416361 -0.306564 0.288137 1.000000

  • 상관관계 히트맵
1
2
3
4
5
6
7
8
9
10
11
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize=(16, 5))

# 기본 그래프 [Basic Correlation Heatmap]
sns.heatmap(num_mpg.corr(), ax=ax[0])
ax[0].set_title('Basic Correlation Heatmap', pad = 12)

# 상관관계 수치 그래프 [Correlation Heatmap with Number]
sns.heatmap(num_mpg.corr(), vmin=-1, vmax=1, annot=True, ax=ax[1])
ax[1].set_title('Correlation Heatmap with Number', pad = 12)

plt.show()
Output

png

위의 코드에서 pad는 히트맵과 타이틀의 간격설정이며,
set_title의 인자를 설명하면 (히트맵을 만들 ‘데이터셋.corr()’, 히트맵의 최소값, 최대값, 수치표현(bool값), 마지막인자는 확실하지는 않지만 앞의 히트맵 설정을 어떤 히트맵에 적용시킬지 묻는것 같다.)


상관관계 배열 만들기
1
2
3
4
# import numpy as np
# 윗단 코드에서 만들어진 num_mpg 사용
print(int(True))
np.triu(np.ones_like(num_mpg.corr()))
1
array([[1., 1., 1., 1., 1., 1., 1.],
       [0., 1., 1., 1., 1., 1., 1.],
       [0., 0., 1., 1., 1., 1., 1.],
       [0., 0., 0., 1., 1., 1., 1.],
       [0., 0., 0., 0., 1., 1., 1.],
       [0., 0., 0., 0., 0., 1., 1.],
       [0., 0., 0., 0., 0., 0., 1.]])

np.triu(배열, k=0)는 위 결과처럼 우하향 대각선이 있고 위 아래로 삼각형이 있다 생각했을때 아래쪽의 삼각형이 모두 0이 되는 함수이다.
k의 숫자가 낮아질수록 삼각형은 한칸씩 작아진다.
위 결과에서 행과 열이 7칸이 된 이유는 np.ones_like(num_mpg.corr())의 행이 7개 이기때문인듯 하다.
확실히 모르겠음 질문 필수


1
2
mask = np.triu(np.ones_like(num_mpg.corr(), dtype=np.bool))
print(mask)
[[ True  True  True  True  True  True  True]
 [False  True  True  True  True  True  True]
 [False False  True  True  True  True  True]
 [False False False  True  True  True  True]
 [False False False False  True  True  True]
 [False False False False False  True  True]
 [False False False False False False  True]]

k 값을 바꿔 True와 False로 값을 준 경우.

1
2
3
4
5
6
7
8
9
10
# 기본주석 생략
fig, ax = plt.subplots(figsize=(16, 5))

# 기본 그래프 [Basic Correlation Heatmap]
ax = sns.heatmap(num_mpg.corr(), mask=mask,
vmin=-1, vmax = 1,
annot=True,
cmap="BrBG", cbar = True)
ax.set_title('Triangle Correlation Heatmap', pad = 16, size = 16)
fig.show()
Output

png

위의 글들을 모두 읽었음에도 단 하나 모르는 요소가 있다면 바로 cmap일 것이다.
cmap은 colormap을 줄인것으로 cmap의 종류는 상당히 많다.
이곳에 가면 상당히 잘 정리되어 있으니 cmap옵션을 사용할 때마다 요긴하게 쓸 수 있을것이다.

Intermediate

페가블로그 코드


  • 이 챕터의 내용은 코드가 너무 긺으로 시각화 결과물을 접지않고 코드를 접는형식으로 서술하겠음.

  • 필수 코드이므로 생략을 생략

    1
    2
    3
    4
    import matplotlib.pyplot as plt
    from matplotlib.ticker import (MultipleLocator, AutoMinorLocator, FuncFormatter)
    import seaborn as sns
    import numpy as np
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def plot_example(ax, zorder=0):
ax.bar(tips_day["day"], tips_day["tip"], color="lightgray", zorder=zorder)
ax.set_title("tip (mean)", fontsize=16, pad=12)

# Values
h_pad = 0.1
for i in range(4):
fontweight = "normal"
color = "k"
if i == 3:
fontweight = "bold"
color = "darkred"

ax.text(i, tips_day["tip"].loc[i] + h_pad, f"{tips_day['tip'].loc[i]:0.2f}",
horizontalalignment='center', fontsize=12, fontweight=fontweight, color=color)

# Sunday
ax.patches[3].set_facecolor("darkred")
ax.patches[3].set_edgecolor("black")

# set_range
ax.set_ylim(0, 4)
return ax

def major_formatter(x, pos):
return "{%.2f}" % x
formatter = FuncFormatter(major_formatter)

1
2
3
tips = sns.load_dataset("tips")
tips_day = tips.groupby("day").mean().reset_index()
print(tips_day)
    day  total_bill       tip      size
0  Thur   17.682742  2.771452  2.451613
1   Fri   17.151579  2.734737  2.105263
2   Sat   20.441379  2.993103  2.517241
3   Sun   21.410000  3.255132  2.842105

Code
1
2
fig, ax = plt.subplots(figsize=(10, 6))
ax = plot_example(ax, zorder=2)

png

Code
1
2
3
4
5
6
fig, ax = plt.subplots(figsize=(10, 6))
ax = plot_example(ax, zorder=2)

ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)

png

Code
1
2
3
4
5
6
7
8
9
10
fig, ax = plt.subplots()
ax = plot_example(ax, zorder=2)

ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)

ax.yaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_major_formatter(formatter)
ax.yaxis.set_minor_locator(MultipleLocator(0.5))

png

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
fig, ax = plt.subplots()
ax = plot_example(ax, zorder=2)

ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)

ax.yaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_major_formatter(formatter)
ax.yaxis.set_minor_locator(MultipleLocator(0.5))

ax.grid(axis="y", which="major", color="lightgray")
ax.grid(axis="y", which="minor", ls=":")

png

책 코드


Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator, FuncFormatter)
import seaborn as sns
import numpy as np

tips = sns.load_dataset("tips")
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize=(16, 5))

def major_formatter(x, pos):
return "%.2f$" % x
formatter = FuncFormatter(major_formatter)

# Ideal Bar Graph
ax0 = sns.barplot(x = "day", y = 'total_bill', data = tips,
ci=None, color='lightgray', alpha=0.85, zorder=2,
ax=ax[0])

png

Code
1
2
3
4
5
group_mean = tips.groupby(['day'])['total_bill'].agg('mean')
h_day = group_mean.sort_values(ascending=False).index[0]
h_mean = np.round(group_mean.sort_values(ascending=False)[0], 2)
print("The Best Day:", h_day)
print("The Highest Avg. Total Biil:", h_mean)
The Best Day: Sun
The Highest Avg. Total Biil: 21.41
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize=(16, 5))

# Ideal Bar Graph
ax0 = sns.barplot(x = "day", y = 'total_bill', data = tips,
ci=None, color='lightgray', alpha=0.85, zorder=2,
ax=ax[0])

group_mean = tips.groupby(['day'])['total_bill'].agg('mean')
h_day = group_mean.sort_values(ascending=False).index[0]
h_mean = np.round(group_mean.sort_values(ascending=False)[0], 2)
for p in ax0.patches:
fontweight = "normal"
color = "k"
height = np.round(p.get_height(), 2)
if h_mean == height:
fontweight="bold"
color="darkred"
p.set_facecolor(color)
p.set_edgecolor("black")
ax0.text(p.get_x() + p.get_width()/2., height+1, height, ha = 'center', size=12, fontweight=fontweight, color=color)

fig.show()

png

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator, FuncFormatter)
import seaborn as sns
import numpy as np

tips = sns.load_dataset("tips")
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize=(16, 5))

def major_formatter(x, pos):
return "%.2f$" % x
formatter = FuncFormatter(major_formatter)

# Ideal Bar Graph
ax0 = sns.barplot(x = "day", y = 'total_bill', data = tips,
ci=None, color='lightgray', alpha=0.85, zorder=2,
ax=ax[0])

group_mean = tips.groupby(['day'])['total_bill'].agg('mean')
h_day = group_mean.sort_values(ascending=False).index[0]
h_mean = np.round(group_mean.sort_values(ascending=False)[0], 2)
for p in ax0.patches:
fontweight = "normal"
color = "k"
height = np.round(p.get_height(), 2)
if h_mean == height:
fontweight="bold"
color="darkred"
p.set_facecolor(color)
p.set_edgecolor("black")
ax0.text(p.get_x() + p.get_width()/2., height+1, height, ha = 'center', size=12, fontweight=fontweight, color=color)

ax0.set_ylim(-3, 30)
ax0.set_title("Ideal Bar Graph", size = 16)

ax0.spines['top'].set_visible(False)
ax0.spines['left'].set_position(("outward", 20))
ax0.spines['left'].set_visible(False)
ax0.spines['right'].set_visible(False)

ax0.yaxis.set_major_locator(MultipleLocator(10))
ax0.yaxis.set_major_formatter(formatter)
ax0.yaxis.set_minor_locator(MultipleLocator(5))

ax0.set_ylabel("Avg. Total Bill($)", fontsize=14)

ax0.grid(axis="y", which="major", color="lightgray")
ax0.grid(axis="y", which="minor", ls=":")

fig.show()

png

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator, FuncFormatter)
import seaborn as sns
import numpy as np

tips = sns.load_dataset("tips")
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize=(16, 5))

def major_formatter(x, pos):
return "%.2f$" % x
formatter = FuncFormatter(major_formatter)

# Ideal Bar Graph
ax0 = sns.barplot(x = "day", y = 'total_bill', data = tips,
ci=None, color='lightgray', alpha=0.85, zorder=2,
ax=ax[0])

group_mean = tips.groupby(['day'])['total_bill'].agg('mean')
h_day = group_mean.sort_values(ascending=False).index[0]
h_mean = np.round(group_mean.sort_values(ascending=False)[0], 2)
for p in ax0.patches:
fontweight = "normal"
color = "k"
height = np.round(p.get_height(), 2)
if h_mean == height:
fontweight="bold"
color="darkred"
p.set_facecolor(color)
p.set_edgecolor("black")
ax0.text(p.get_x() + p.get_width()/2., height+1, height, ha = 'center', size=12, fontweight=fontweight, color=color)

ax0.set_ylim(-3, 30)
ax0.set_title("Ideal Bar Graph", size = 16)

ax0.spines['top'].set_visible(False)
ax0.spines['left'].set_position(("outward", 20))
ax0.spines['left'].set_visible(False)
ax0.spines['right'].set_visible(False)

ax0.yaxis.set_major_locator(MultipleLocator(10))
ax0.yaxis.set_major_formatter(formatter)
ax0.yaxis.set_minor_locator(MultipleLocator(5))

ax0.set_ylabel("Avg. Total Bill($)", fontsize=14)

ax0.grid(axis="y", which="major", color="lightgray")
ax0.grid(axis="y", which="minor", ls=":")

ax0.set_xlabel("Weekday", fontsize=14)
for xtick in ax0.get_xticklabels():
print(xtick)
if xtick.get_text() == h_day:
xtick.set_color("darkred")
xtick.set_fontweight("demibold")
ax0.set_xticklabels(['Thursday', 'Friday', 'Saturday', 'Sunday'], size=12)

ax1 = sns.barplot(x = "day", y = 'total_bill', data = tips,
ci=None, alpha=0.85,
ax=ax[1])
for p in ax1.patches:
height = np.round(p.get_height(), 2)
ax1.text(p.get_x() + p.get_width()/2., height+1, height, ha = 'center', size=12)
ax1.set_ylim(-3, 30)
ax1.set_title("Just Bar Graph")

plt.show()
Text(0, 0, 'Thur')
Text(0, 0, 'Fri')
Text(0, 0, 'Sat')
Text(0, 0, 'Sun')

png

pandas 기본 문법

DataFrame 생성 방법


  • list이용

    1
    2
    3
    4
    5

    import pandas as pd

    frame = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    frame
출력

0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
  • Dictionary 이용

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import pandas as pd

    data = {
    'age' : [20,39,41],
    'height' : [176, 182, 180],
    'weight' : [73, 78, 69]
    }
    indexName = ['사람1', '사람2', '사람3']

    frame = pd.DataFrame(data, index = indexName)
    frame
출력

age height weight
사람1 20 176 73
사람2 39 182 78
사람3 41 180 69

Sample Dataset 가져오기


위처럼 직접 DataFrame을 만드는 것이 아닌 제공하는 Dataset을 직접 가져오는 방법도 있다.
Dataset을 가져오는 방법은 다음과 같다.

  1. Dataset Github에 접속하고 가져오고싶은 데이터셋을 고른다.
  2. 예를들어 flights.csv 를 가져오고 싶다면
    1
    2
    3
    4
    import seaborn as sns
    flights = sns.load_dataset("flights") #여기까지가 가져오기
    flights.head(5) # 다섯번째 행의 데이터까지만 출력
    flights["year"] # 'year'열만 출력
    위와 같이 제공되는 데이터셋을 가져올 수 있다.

DataFrame 조회 방법


기본적인 조회 방법

DataFrame의 기본적인 조회 방법은 다음과 같다.


1
2
# 위에서 가져온 데이터셋 flights를 사용
flights.head() # 데이터프레임의 가장 첫부분부터 표시
출력

year month passengers
0 1949 Jan 112
1 1949 Feb 118
2 1949 Mar 132
3 1949 Apr 129
4 1949 May 121

이 때 .head()의 괄호 안에 숫자가 있다면 그 수의 개수만큼 데이터가 출력된다.

  • .tail()


1
flights.tail() #데이터프레임의 가장 뒷부분부터 표시
출력

year month passengers
139 1960 Aug 606
140 1960 Sep 508
141 1960 Oct 461
142 1960 Nov 390
143 1960 Dec 432

.tail()역시 마찬가지로 괄호안에 숫자가 있다면 수의 개수만큼 데이터가 출력된다.

  • .index


데이터프레임의 인덱스를 표시하는 방법도 있다.

1
flights.index
RangeIndex(start=0, stop=144, step=1)

열(Column) 조회 방법

1
2
3
4
5
6
7
8
9
10
#열(Column) 조회
print ("* 열 조회 - 1")
print (frame['age'])
print ("* 열 조회 - 2")
print(frame.age)

#특정 열의 특정 값을 조회하고 싶을때
print("* 특정 열 의 특정 값 조회")
print(frame['age'][1])
print(frame.height[2])
출력
* 열 조회 - 1
사람1    20
사람2    39
사람3    41
Name: age, dtype: int64
* 열 조회 - 2
사람1    20
사람2    39
사람3    41
Name: age, dtype: int64
* 특정 열 의 특정 값 조회
39
180

행(Row) 조회

행 조회는 열 조회와 조금 다르게 lociloc를 사용해서 조회 할 수 있다.
여기서 loc는 사람이 읽을 수 있는 라벨 값으로 특정 값들을 골라오는 방법이고,
iloc는 행이나 칼럼의 순서를 나타내는 정수로 특정 값을 추출하는 방법이다.

1
2
3
4
5
#행(Row) 조회 (loc)
print("* loc 특정 행 조회")
print(frame.loc['사람1'])

# print(frame.loc[0]) - 조건이 정수이므로 조회 불가
출력
* 특정 행 조회
age        20
height    176
weight     73
Name: 사람1, dtype: int64
loc를 Seq로 조회할 경우
1
2
3
4
5
#행(Row) 조회 (iloc)
print("* iloc 특정 행 조회")
print(frame.iloc[0])

# print(frame.iloc['사람1']) - 조건이 정수가 아니므로 조회 불가
출력
* iloc 특정 행 조회
age        20
height    176
weight     73
Name: 사람1, dtype: int64

DataFrame 수정 방법


열(Column) 추가하기

gender 라는 컬럼을 추가합니다.

1
2
frame_add_col = pd .DataFrame(frame,columns= ['age','height','weight','gender'])
frame_add_col
출력

age height weight gender
사람1 20 176 73 NaN
사람2 39 182 78 NaN
사람3 41 180 69 NaN

컬럼이 추가되었고 어떠한 값도 넣어주지 않았으므로 NaN 값이 출력되고있다.
이제 데이터를 입력해준다.

1
2
frame_add_col['gender'] = ['male', 'male', 'female']
frame_add_col
출력

age height weight gender
사람1 20 176 73 male
사람2 39 182 78 male
사람3 41 180 69 female

행(Row) 추가하기

1
2
3
frame_add_index = frame_add_col.copy()
frame_add_index.loc['사람4'] = [31, 158, 48, 'female']
frame_add_index
출력

age height weight gender
사람1 20 176 73 male
사람2 39 182 78 male
사람3 41 180 69 female
사람4 31 158 48 female

행, 열 삭제하기

drop 메소드를 사용하면 행 또는 열을 삭제할 수 있다.
axis 값은 행이면’0’, 열이면 ‘1’로 지정해주면 된다.

1
2
print('remove age column')
frame_add_col.drop("height", axis=1)
출력
remove age column

age weight gender
사람1 20 73 male
사람2 39 78 male
사람3 41 69 female

그러나 이 경우 기존에 있던 frame_add_col에서 삭제되는게 아니라 삭제된 상태의 프레임을 리턴해준 것이다.
그러므로 기존 프레임에 적용하기 위해서 inplace = True 옵션을 추가로 주어야 한다.

1
2
frame_add_index.drop('사람2', axis=0, inplace = True)
frame_add_index
출력

age height weight gender
사람1 20 176 73 male
사람3 41 180 69 female
사람4 31 158 48 female

References

파이썬(Python) 기본 문법 - 1

이 포스트는 필자의 정확한 파이썬 문법을 익히고 필요할때 찾아보기 위해 서술한 것이다.

Hello World


어떤 프로그래밍언어든 배우기 시작하면 출력하고 보는 Hello world, 파이썬에서는 다음과 같이 출력한다.

1
print("Hello, world!")

Output:

Hello, world!

당연하게도 Hello, world 이외의 다른 문장이 들어가면 그대로 출력되며
print() 에서 괄호 내부에 출력을 해주고싶은 변수나 문장을 입력하면 된다, 문장의 경우는 따옴표로 묶어줘야 출력이 된다.

주석처리


접기 / 펼치기

프로그래밍 언어마다 주석처리를 해주는 방법이 다르다, 파이썬의 경우에는 다음과 같이 주석처리한다.

1
2
3
4
5
6
7
# 한줄을 주석처리하는 방법입니다.
"""
여러줄을
한번에 주석처리하는
방법입니다.
"""
print("Hello, world!")

Output:

Hello, world!

위처럼 작성하고 실행시키면 나머지 줄은 모두 주석처리되고 가장 아랫줄인 Hello, world만 출력이 되는걸 볼 수 있다.

변수의 종류


접기 / 펼치기

변수(Variable)는 (문자나 숫자 같은) 값을 담는 컨테이너로 값을 유지할 필요가 있을 때 사용한다. 여기에 담겨진 값은 다른 값으로 바꿀 수 있다. 변수는 마치 (사람이 쓰는 언어인) 자연어에서 대명사와 비슷한 역할을 한다.

출처 : 생활코딩 - 변수

다른 프로그래밍언어와 같이 파이썬 역시 다양한 변수의 종류(타입)가 있는데 이번 단락에서는 그것에 대해 알아보겠다.

int타입 (정수형)

1
2
num_int = 1
print(type(num_int))

변수에 값을 정수로 주고 그 변수의 타입을 알아본 예제, 출력을 하게되면 <class 'int'>가 줄력된다.

float타입 (실수형)

1
2
num_float = 0.2
print(type(num_float))

변수에 값을 실수로 주고 그 변수의 타입을 출력한 예제, 출력을 하게되면 <class 'float'>가 출력된다.

bool타입 (논리형)

1
2
bool_true = True
print(type(bool_true))

변수에 값을 논리타입(True or False)으로 주고 그 변수의 타입을 출력한 예제, 출력하면 <class 'bool>이 출력된다.

None타입

1
2
none_x = None
print(type(none_x))

Null을 나타내는 자료형이다, None라는 한가지 값만 가질 수 있다. (왜 필요한지는 아직 모르겠다)

사칙연산


접기 / 펼치기

파이썬에서의 사칙연산은 일반적인 사칙연산과 같다.
그리고 나눈후 정수의값만 구하는 //, 나머지를 구하는 %, 거듭제곱을 뜻하는 ** 등의 연산자가 있다.

1
2
3
4
5
6
7
8
9
a = 3
b = 2
print('a + b = ', a+b)
print('a - b = ', a-b)
print('a * b = ', a*b)
print('a / b = ', a/b)
print('a // b = ', a//b)
print('a % b = ', a%b)
print('a ** b = ', a**b)

Output:

a + b =  5
a - b =  1
a * b =  6
a / b =  1.5
a // b =  1
a % b =  1
a ** b =  9

위처럼 각각 계산이 된걸 알 수 있다.

정리하면 아래와 같다

연산자 내용
+ 두 변수의 합을 계산
- 두 변수의 차를 계산
* 두 변수의 곱을 계산
/ 두 변수로 나눈 결과를 float 형으로 반환
// 두 변수로 나눈 결과에서 정수 부분만 취함
% 두 변수로 나눈 결과에서 나머지 값만 가져옴
** i**j일 경우, i의 j만큼 제곱하여 계산 (예: 2 ** 4 = 24 = 16)

논리형 연산자


접기 / 펼치기

논리형 연산자에는 andor이 있다.
and연산자는 두 조건이 모두 참일때 True가 되며 or의 경우 두 조건중 하나라도 참일때 True가 된다.

and연산자

1
2
3
4
print(True and True)
print(True and False)
print(False and True)
print(False and False)

Output:

True
False
False
False

위 결과처럼 두 조건 모두 참일때만 True를 반환한다.
표로 나타내면 다음과 같다.

변수1 변수2 AND 연산결과
True True True
True False False
False True False
False False False

or 연산자

1
2
3
4
print(True or True)
print(True or False)
print(False or True)
print(False or False)

Output:

True
True
True
False

위 결과처럼 두 조건 중 하나만 참이라도 True를 반환한다.
표로 나타내면 다음과 같다.

변수1 변수2 AND 연산결과
True True True
True False True
False True True
False False False

비교 연산자


접기 / 펼치기

비교 연산자에는 >,<,>=,<=이 있다.
일단, 예제를 보자.

1
2
3
4
print(4 > 3)
print(4 < 3)
print(4 >= 3)
print(4 <= 3)

Output:

True
False
True
False

예제처럼 결과는 논리타입으로 출력된다.

문자열 연산


접기 / 펼치기

정수나 실수 논리타입뿐만 아니라 문자열도 연산이 가능하다.
다만 문자열을 뒤에 덧붙이는+연산자, 문자열을 횟수만큼 반복해주는*연산자만 사용이 가능하다.

1
2
3
str1 = "Python "
str2 = "Editor "
print('str1 + str2 = ', str1 + str2)

Output:

Python Editor

+연산자의 경우 위처럼 문자열 두 개가 나란히 이어붙혀져 출력이 되며,

1
2
greet = str1 + str2
print('greet * 3 = ', greet * 3)

Output:

Python Editor Python Editor Python Editor 

*연산자의 경우 변수에 담긴 문자열이 정해준 횟수만큼 반복되어 나열된다.

문자열 인덱싱


접기 / 펼치기

문자열이 있는경우 숫자을 통해 문자열에서 특정 문자만을 출력할 수 있는데 이를 Indexing 이라고 한다.
Hello world이라는 문자열이 있다고 하자 그럼 문자열의 각 인덱스는 다음과 같다.

문자열 H e l l o w o r l d
인덱스 0 1 2 3 4 5 6 7 8 9 10

이처럼 각 글자마다 인덱스가 배정되며 공백에도 인덱스가 배정된다.
인덱스를 사용하면 다음과 같은 것도 가능하다.

1
2
3
4
text_ex = "Hello world"
print(text_ex[2])
print(text_ex[6:10])
print(text_ex[2:11:2])

Output:

l
worl
lowrd

위 예제는 문자열을 담은 변수에 인덱싱을 한 것이다
첫번째 줄은 인덱스’2’의 문자를 가져오는 것인데 인덱스는 0부터 시작하므로 (2번째가아닌)3번째인’l’을 출력한것이다.
두번째 줄은 인덱스’6’부터 ‘9’까지(두번째인덱스-1)의 숫자를 가져오는 것이므로 ‘worl’이 출력되었다.
세번째 줄은 인덱스’2’부터 ‘10’까지를 가져오되, 한칸씩 건너뛰고(세번째 숫자가 3이므로) 가져오는것이다.

리스트(list)


접기 / 펼치기

리스트는 여러개의 문자열, 변수, 숫자 등을 담을수 있는 자료구조이다.
리스트의 장점은 다음과 같다.

  • 인덱스 번호로 빠른 접근이 가능하다.
  • 데이터의 위치에 대해 직접적인 접근(Access)가 가능하다.
    1
    fruit = [['apple', 'banana', 'cherry'], 123]
    위가 리스트의 형태이다.
    리스트의 값은 기본적으로 인덱스가 배정된다 이때는
    1
    print(fruit[0])
    Output: [‘apple’, ‘banana’, ‘cherry’]
    위와 같은 형태로 나타낼 수 있으며 해당 인덱스의 요소가 리스트라면 리스트 전체를 출력한다.

만약 위처럼 리스트가 중첩된 형태라면

1
print(fruit[0][1])

Output:

banana

위처럼 출력이 가능하며 이때 리스트의 요소중 해당 인덱스의 요소가 출력된다.
물론 이 때도 출력된 문자열에서 다음과 같이 문자열의 요소를 출력하는것도 가능하다.

1
print(fruit[0][1][3])

Output:

a

위와같이 결과가 출력된다.

리스트값 수정, 추가, 삭제하기


접기 / 펼치기

리스트가 여러 요소들의 집합이다보니 리스트의 값에 변동이 필요할 때가 있다.
리스트는 값의 수정, 추가, 삭제가 가능하므로 기능과 문법에 대해 알아둘 필요가 있다.

리스트 값 수정하기

1
2
3
a = [0,1,2]
a[1] = "b"
print(a)

Output:

[0, 'b', 2]

별다른 문법없이 리스트의 인덱스에 값을 넣어주니 수정이 되는것을 알 수 있다.

리스트 값 추가하기

  • append

    1
    2
    3
    4
    5
    6
    7
    a = [100, 200, 300]
    a.append(400)
    print(a)

    b = [500,600]
    a.append(b)
    print(a)

    Output:

    [100, 200, 300, 400]
    [100, 200, 300, 400, [500, 600]]
    리스트명.append(값)을 통해서 리스트에 값을 추가할 수 있으며 한개의 값만 추가할 수 있다.
    리스트의 경우엔 한가지 값이며 추가할 경우 중첩된 리스트의 형태로 추가가 된다.

  • extend

    extendappend와 거의 같지만 다른점이 하나 있습니다.
    append는 인자(리스트, 튜플 등)를 주어도 인자 그대로를 리스트에 추가하지만,
    extend는 인자를 줄 경우 인자의 값 하나하나를 리스트에 추가한다.

    1
    2
    3
    4
    a = [2, 9, 3]
    b = [1, 2, 3]
    a.extend(b)
    print(a)

    Output:

    [2, 9, 3, 1, 2, 3]
    결과와 같이 append와 비교했을때 extend된 인자의 값 하나하나가 추가된걸 볼 수 있다.

  • insert

    insert는 입력해준 위치의 인덱스에 값을 추가해준다.

    1
    2
    3
    4
    a = [1,2,3]
    print(a)
    a.insert(1,'abc')
    print(a)

    Output:

    [1,2,3]
    [1,’abc’,2,3]

리스트 값 삭제하기

  • remove

    1
    2
    3
    4
    5
    6
    7
    a =[1,2,1,2]
    #리스트의 첫번째 1이 삭제
    a.remove(1)
    print(a)
    #리스트의 두번째 였던 1이 삭제
    a.remove(3)
    print(a)

    Output:

    [2, 1, 2]
    [2, 2]
    리스트명.remove()는 괄호내의 값을 삭제한다.
    만약 값이 리스트내에서 중복될경우 가장 앞에 있는 값을 삭제한다.

  • del

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    a = [0,1,2,3,4,5,6,7,8,9]

    # 1 삭제
    del a[1]
    print(a)

    b = [0,1,2,3,4,5,6,7,8,9]
    # 범위로 삭제
    del b[1:3] #list는 항상 시작하는 index부터, 종료하는 n의 n-1까지의 범위를 잡아준다.
    print(b)

    Output:

    [0, 2, 3, 4, 5, 6, 7, 8, 9]
    [0, 3, 4, 5, 6, 7, 8, 9]
    del 리스트명[인덱스]는 리스트의 인덱스에 위치한 값을 삭제해준다.
    인덱스값에 범위를 주고싶다면 0:4 처럼 넣을수 있으며 이때는 0에서 3번째 값까지 삭제가 된다.

  • pop

    1
    2
    3
    4
    5
    a = [0,1,2,3,4]
    r = a.pop(1)

    print(a)
    print(r)

    Output:

    [0, 2, 3, 4]
    1
    리스트명.pop()은 괄호내의 값을 해당 리스트에서 끄집어낸다.

튜플(tuple)


접기 / 펼치기

튜플은 리스트와 비슷하게 여러개의 문자열, 변수, 숫자 등을 담을수 있는 자료구조이다.
튜플과 리스트의 가장 차이점으로는 튜플은 값에대한 수정이 불가하다는 점이다.
그렇다면 튜플은 무슨 장점이 있느냐 라고 반문할 수 있는데 리스트와 비교한 튜플의 장점은 다음과 같다.

  • 메모리 사용량이 적다.
  • 생성 시간이 빠르다.
  • 인덱스를 사용하여 튜플의 데이터에 접근하는 시간이 비교적 짧다.

튜플의 문법, 기본형태는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
tuple1 = (0) # 끝에 콤마(,)를 붙이지 않았을 때
tuple2 = (0,) # 끝에 콤마(,)를 붙여줬을 때
tuple3 = 0,1,2

print(tuple1)
print(tuple2)
print(tuple3)

print(type(tuple1)) # 콤마(,)를 붙여주지 않으면 튜플이 아닙니다.
print(type(tuple2)) # 콤마(,)를 붙여주어야 튜플 자료형 입니다.
print(type(tuple3)) # 여러개의 값 일경우 괄호를 없애주어도 튜플 자료형 입니다.

Output:

0
(0,)
(0, 1, 2)
<class 'int'>
<class 'tuple'>
<class 'tuple'>

튜플을 생성할때 튜플이 되기위해서는 콤마(,)가 필수적이다.
콤마를 작성하지 않으면 타입을 출력했을때 튜플이 아닌 입력한 변수형태로 출력이 된다.

튜플역시 리스트와 같이 인덱싱및 슬라이싱이 가능하다.

튜플의 연산

튜플도 연산이 가능한데, 더하거나 곱하는 +, * 연산자만 사용이 가능하다.

1
2
3
4
t1 = (0,1,2,3,4)
t2 = ('a','b','c')
t3 = t1+t2
print(t3)

Output:

(0, 1, 2, 3, 4, 'a', 'b', 'c')

딕셔너리


접기 / 펼치기

딕셔너리는 키와 그에따른 값으로 구성되어있는 파이썬의 자료구조이다.

1
2
3
4
5
dic = {'teacher':'alice', 'class': 5, 'studentid': '15', 'list':[1,2,3]}

print(dic['teacher'])
print(dic['class'])
print(dic['list'])

Output:

alice
5
[1, 2, 3]

를 출력하면 그와 대응하는 이 출력되는 자료구조이며 자료에 순서가 없는논시퀀스 자료형이다.

1
2
3
a = {'name': 'bob', 'job': 'farmer', 'age': 35}
a.keys()
a.values()

Output:

dict_keys(['name', 'job', 'age'])
dict_values(['bob', 'farmer', 35])

이렇게 키만 출력할수도, 값만 출력할수도 있다.

집합 연산자


접기 / 펼치기

파이썬에도 집합연산이 있고, 자료구조들의 합,교,차집합에 대한 연산을 할수 있다.
기호는 |,&,-이며, 각각의 예시는 다음과 같다.

1
2
3
4
5
a = {1,2,3,4}
b = {3,4,5,6}
print(a|b)
print(a&b)
print(a-b)

Output:

{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}

if 조건문


접기 / 펼치기

조건문이란 작성자가 명시한 조건식의 결과인 boolean값이 참인지 거짓인지에 따라 달라지는 계산이나 상황을 수행하는 문장이다.

1
2
3
4
5
6
7
8
9
10
a = -5

if a>5:
print('a는 5이상입니다')

elif a > 0:
print("a는 0초과, 5이하입니다")

else:
print("a는 음수입니다")

Output:

a는 음수입니다.

조건식에는 기본적으로 조건식이 들어가지만 TrueFalse등의 직접적인 bool형 변수가 삽입될수도 있으며, and,or 등과 결합하여 여러가지의 조건식을 사용할수도 있다.

반복문 (for,while)


접기 / 펼치기

같은동작을 여러번 반복해야 할 때 같은코드를 여러번 적어넣는건 비효율적이다.
그럴때 반복문을 사용하면 훨씬 적은양의 코드로도 같은효과를 낼 수 있다.

  • for문

  • for문의 기본 구조
    1
    2
    3
    for 변수 in 리스트(또는 튜플, 문자열) :
    수행할 문장1
    수행할 문장2
    리스트나 튜플, 문자열의 첫 번째 요소부터 마지막 요소까지 차례로 변수에 대입되어 “수행할 문장1”, “수행할 문장2” 등이 수행된다.
    1
    2
    3
    a = ['1','2','3']
    for i in a :
    print(i)
    Output: 1
    2
    3

리스트 a의 첫번째 값인 1이 i에 대입되고 print(i)가 출력된다.
다음엔 두번째 값인 2가 대입되고 출력된다.
이것을 마지막 값까지 반복한다.

  • while문

  • while문의 기본 구조
    1
    2
    3
    4
    5
    while <조건문>:
    <수행할 문장1>
    <수행할 문장2>
    <수행할 문장3>
    ...
    while문은 for보다는 간단하다. while, 조건문, 실행문 이 세개면 완성되기 때문이다.
    이러한 특성때문에 while문은 조건문을 거짓으로 만들어주는 문장이 없다면 무한실행된다. 프로그램 뻗는다
    간단한 예제를 보면 다음과 같다.
    1
    2
    3
    4
    i = 0
    while i <= 5 :
    print("{}번째 반복입니다.".format(i))
    i += 1
    Output: 0번째 반복입니다.
    1번째 반복입니다.
    2번째 반복입니다.
    3번째 반복입니다.
    4번째 반복입니다.
    5번째 반복입니다.
    변수 i로 인해 자동으로 조건식이 False가 되면서 while문이 종료되는 모습이다.
    이렇듯 while문은 조건문을 거짓으로 만들어주는 무엇인가가 없다면 종료되지않는다.