TigerCow.Door

'데이터분석'에 해당되는 글 3건

Pandas_clear


안녕하세요. 문범우입니다.

이번 포스팅에서는 파이썬 라이브러리인 pandas(판다스)에 대해서 알아보도록 하겠습니다.


해당 내용은 flearning의 김길호님의 강의를 바탕으로 작성되었습니다.

https://www.flearning.net/courses/6



1. Pandas 란?


Pandas는 파이썬에서 사용하는 데이터분석 라이브러리로, 행과 열로 이루어진 데이터 객체를 만들어 다룰 수 있게 되며 보다 안정적으로 대용량의 데이터들을 처리하는데 매우 편리한 도구 입니다.


먼저 pandas를 사용하기 위해서는 pandas를 설치한 이후에 아래와 같이 import를 해야 합니다.


import pandas as pd


아래 실습에서는 jupyter notebook을 사용하였습니다.



Pandas 기초

1. Pandas 란?

In [2]:
# pandas 사용하기
import numpy as np # numpy 도 함께 import
import pandas as pd

2. Pandas 자료구조

Pandas에서는 기본적으로 정의되는 자료구조인 Series와 Data Frame을 사용합니다.

이 자료구조들은 빅 데이터 분석에 있어서 높은 수준의 성능을 보여줍니다.

2-1. Series

먼저 Series에 대해서 알아보도록 하겠습니다.

In [3]:
# Series 정의하기
obj = pd.Series([4, 7, -5, 3])
obj
Out[3]:
0    4
1    7
2   -5
3    3
dtype: int64
In [4]:
# Series의 값만 확인하기
obj.values
Out[4]:
array([ 4,  7, -5,  3])
In [5]:
# Series의 인덱스만 확인하기
obj.index
Out[5]:
RangeIndex(start=0, stop=4, step=1)
In [7]:
# Series의 자료형 확인하기
obj.dtypes
Out[7]:
dtype('int64')
In [8]:
# 인덱스를 바꿀 수 있다.
obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
obj2
Out[8]:
d    4
b    7
a   -5
c    3
dtype: int64
In [10]:
# python의 dictionary 자료형을 Series data로 만들 수 있다.
# dictionary의 key가 Series의 index가 된다
sdata = {'Kim': 35000, 'Beomwoo': 67000, 'Joan': 12000, 'Choi': 4000}
obj3 = pd.Series(sdata)
obj3
Out[10]:
Kim        35000
Beomwoo    67000
Joan       12000
Choi        4000
dtype: int64
In [12]:
obj3.name = 'Salary'
obj3.index.name = "Names"
obj3
Out[12]:
Names
Kim        35000
Beomwoo    67000
Joan       12000
Choi        4000
Name: Salary, dtype: int64
In [13]:
# index 변경
obj3.index = ['A', 'B', 'C', 'D']
obj3
Out[13]:
A    35000
B    67000
C    12000
D     4000
Name: Salary, dtype: int64

2-2. Data Frame

이번에는 Data Frame에 대해서 알아보도록 하겠습니다.

In [23]:
# Data Frame 정의하기
# 이전에 DataFrame에 들어갈 데이터를 정의해주어야 하는데,
# 이는 python의 dictionary 또는 numpy의 array로 정의할 수 있다.
data = {'name': ['Beomwoo', 'Beomwoo', 'Beomwoo', 'Kim', 'Park'],
        'year': [2013, 2014, 2015, 2016, 2015],
        'points': [1.5, 1.7, 3.6, 2.4, 2.9]}
df = pd.DataFrame(data)
df
Out[23]:
name year points
0 Beomwoo 2013 1.5
1 Beomwoo 2014 1.7
2 Beomwoo 2015 3.6
3 Kim 2016 2.4
4 Park 2015 2.9
In [24]:
# 행과 열의 구조를 가진 데이터가 생긴다.
In [25]:
# 행 방향의 index
df.index
Out[25]:
RangeIndex(start=0, stop=5, step=1)
In [26]:
# 열 방향의 index
df.columns
Out[26]:
Index(['name', 'year', 'points'], dtype='object')
In [27]:
# 값 얻기
df.values
Out[27]:
array([['Beomwoo', 2013, 1.5],
       ['Beomwoo', 2014, 1.7],
       ['Beomwoo', 2015, 3.6],
       ['Kim', 2016, 2.4],
       ['Park', 2015, 2.9]], dtype=object)
In [28]:
# 각 인덱스에 대한 이름 설정하기
df.index.name = 'Num'
df.columns.name = 'Info'
df
Out[28]:
Info name year points
Num
0 Beomwoo 2013 1.5
1 Beomwoo 2014 1.7
2 Beomwoo 2015 3.6
3 Kim 2016 2.4
4 Park 2015 2.9
In [29]:
# DataFrame을 만들면서 columns와 index를 설정할 수 있다.
df2 = pd.DataFrame(data, columns=['year', 'name', 'points', 'penalty'],
                  index=['one', 'two', 'three', 'four', 'five'])
df2
Out[29]:
year name points penalty
one 2013 Beomwoo 1.5 NaN
two 2014 Beomwoo 1.7 NaN
three 2015 Beomwoo 3.6 NaN
four 2016 Kim 2.4 NaN
five 2015 Park 2.9 NaN

DataFrame을 정의하면서, data로 들어가는 python dictionary와 columns의 순서가 달라도 알아서 맞춰서 정의된다.

하지만 data에 포함되어 있지 않은 값은 NaN(Not a Number)으로 나타나게 되는데,

이는 null과 같은 개념이다.

NaN값은 추후에 어떠한 방법으로도 처리가 되지 않는 데이터이다.

따라서 올바른 데이터 처리를 위해 추가적으로 값을 넣어줘야 한다.

In [31]:
# describe() 함수는 DataFrame의 계산 가능한 값들에 대한 다양한 계산 값을 보여준다.
df2.describe()
Out[31]:
year points
count 5.000000 5.000000
mean 2014.600000 2.420000
std 1.140175 0.864292
min 2013.000000 1.500000
25% 2014.000000 1.700000
50% 2015.000000 2.400000
75% 2015.000000 2.900000
max 2016.000000 3.600000

3. DataFrame Indexing

In [33]:
data = {"names": ["Kilho", "Kilho", "Kilho", "Charles", "Charles"],
           "year": [2014, 2015, 2016, 2015, 2016],
           "points": [1.5, 1.7, 3.6, 2.4, 2.9]}
df = pd.DataFrame(data, columns=["year", "names", "points", "penalty"],
                          index=["one", "two", "three", "four", "five"])
df
Out[33]:
year names points penalty
one 2014 Kilho 1.5 NaN
two 2015 Kilho 1.7 NaN
three 2016 Kilho 3.6 NaN
four 2015 Charles 2.4 NaN
five 2016 Charles 2.9 NaN

3-1. DataFrame에서 열을 선택하고 조작하기

In [34]:
df['year']
Out[34]:
one      2014
two      2015
three    2016
four     2015
five     2016
Name: year, dtype: int64
In [36]:
# 동일한 의미를 갖는, 다른 방법
df.year
Out[36]:
one      2014
two      2015
three    2016
four     2015
five     2016
Name: year, dtype: int64
In [37]:
df[['year','points']]
Out[37]:
year points
one 2014 1.5
two 2015 1.7
three 2016 3.6
four 2015 2.4
five 2016 2.9
In [38]:
# 특정 열에 대해 위와 같이 선택하고, 우리가 원하는 값을 대입할 수 있다.
df['penalty'] = 0.5
In [39]:
df
Out[39]:
year names points penalty
one 2014 Kilho 1.5 0.5
two 2015 Kilho 1.7 0.5
three 2016 Kilho 3.6 0.5
four 2015 Charles 2.4 0.5
five 2016 Charles 2.9 0.5
In [42]:
# 또는
df['penalty'] = [0.1, 0.2, 0.3, 0.4, 0.5] # python의 List나 numpy의 array
In [43]:
df
Out[43]:
year names points penalty
one 2014 Kilho 1.5 0.1
two 2015 Kilho 1.7 0.2
three 2016 Kilho 3.6 0.3
four 2015 Charles 2.4 0.4
five 2016 Charles 2.9 0.5
In [44]:
# 새로운 열을 추가하기
df['zeros'] = np.arange(5)
In [45]:
df
Out[45]:
year names points penalty zeros
one 2014 Kilho 1.5 0.1 0
two 2015 Kilho 1.7 0.2 1
three 2016 Kilho 3.6 0.3 2
four 2015 Charles 2.4 0.4 3
five 2016 Charles 2.9 0.5 4
In [49]:
# Series를 추가할 수도 있다.
val = pd.Series([-1.2, -1.5, -1.7], index=['two','four','five'])
In [50]:
df['debt'] = val
In [51]:
df
Out[51]:
year names points penalty zeros debt
one 2014 Kilho 1.5 0.1 0 NaN
two 2015 Kilho 1.7 0.2 1 -1.2
three 2016 Kilho 3.6 0.3 2 NaN
four 2015 Charles 2.4 0.4 3 -1.5
five 2016 Charles 2.9 0.5 4 -1.7

하지만 Series로 넣을 때는 val와 같이 넣으려는 data의 index에 맞춰서 데이터가 들어간다.

이점이 python list나 numpy array로 데이터를 넣을때와 가장 큰 차이점이다.

In [52]:
df['net_points'] = df['points'] - df['penalty']
In [53]:
df['high_points'] = df['net_points'] > 2.0
In [54]:
df
Out[54]:
year names points penalty zeros debt net_points high_points
one 2014 Kilho 1.5 0.1 0 NaN 1.4 False
two 2015 Kilho 1.7 0.2 1 -1.2 1.5 False
three 2016 Kilho 3.6 0.3 2 NaN 3.3 True
four 2015 Charles 2.4 0.4 3 -1.5 2.0 False
five 2016 Charles 2.9 0.5 4 -1.7 2.4 True
In [55]:
# 열 삭제하기
del df['high_points']
In [56]:
del df['net_points']
del df['zeros']
In [57]:
df
Out[57]:
year names points penalty debt
one 2014 Kilho 1.5 0.1 NaN
two 2015 Kilho 1.7 0.2 -1.2
three 2016 Kilho 3.6 0.3 NaN
four 2015 Charles 2.4 0.4 -1.5
five 2016 Charles 2.9 0.5 -1.7
In [58]:
df.columns
Out[58]:
Index(['year', 'names', 'points', 'penalty', 'debt'], dtype='object')
In [59]:
df.index.name = 'Order'
df.columns.name = 'Info'
In [60]:
df
Out[60]:
Info year names points penalty debt
Order
one 2014 Kilho 1.5 0.1 NaN
two 2015 Kilho 1.7 0.2 -1.2
three 2016 Kilho 3.6 0.3 NaN
four 2015 Charles 2.4 0.4 -1.5
five 2016 Charles 2.9 0.5 -1.7

3-2. DataFrame에서 행을 선택하고 조작하기

pandas에서는 DataFrame에서 행을 인덱싱하는 방법이 무수히 많다.

물론 위에서 소개했던 열을 선택하는 방법도 수많은 방법중에 하나에 불과하다.

In [61]:
# 0번째 부터 2(3-1) 번째까지 가져온다.
# 뒤에 써준 숫자번째의 행은 뺀다.
df[0:3]
Out[61]:
Info year names points penalty debt
Order
one 2014 Kilho 1.5 0.1 NaN
two 2015 Kilho 1.7 0.2 -1.2
three 2016 Kilho 3.6 0.3 NaN
In [63]:
# tow라는 행부터 four라는 행까지 가져온다.
# 뒤에 써준 이름의 행을 빼지 않는다.
df['two':'four'] # 하지만 비추천!
Out[63]:
Info year names points penalty debt
Order
two 2015 Kilho 1.7 0.2 -1.2
three 2016 Kilho 3.6 0.3 NaN
four 2015 Charles 2.4 0.4 -1.5
In [65]:
# 아래 방법을 권장한다. 
# .loc 또는 .iloc 함수를 사용하는 방법.
df.loc['two'] # 반환 형태는 Series
Out[65]:
Info
year        2015
names      Kilho
points       1.7
penalty      0.2
debt        -1.2
Name: two, dtype: object
In [67]:
df.loc['two':'four']
Out[67]:
Info year names points penalty debt
Order
two 2015 Kilho 1.7 0.2 -1.2
three 2016 Kilho 3.6 0.3 NaN
four 2015 Charles 2.4 0.4 -1.5
In [69]:
df.loc['two':'four', 'points']
Out[69]:
Order
two      1.7
three    3.6
four     2.4
Name: points, dtype: float64
In [70]:
df.loc[:,'year'] # == df['year']
Out[70]:
Order
one      2014
two      2015
three    2016
four     2015
five     2016
Name: year, dtype: int64
In [71]:
df.loc[:,['year','names']]
Out[71]:
Info year names
Order
one 2014 Kilho
two 2015 Kilho
three 2016 Kilho
four 2015 Charles
five 2016 Charles
In [72]:
df.loc['three':'five','year':'penalty']
Out[72]:
Info year names points penalty
Order
three 2016 Kilho 3.6 0.3
four 2015 Charles 2.4 0.4
five 2016 Charles 2.9 0.5
In [73]:
# 새로운 행 삽입하기
df.loc['six',:] = [2013,'Jun',4.0,0.1,2.1]
In [74]:
df
Out[74]:
Info year names points penalty debt
Order
one 2014.0 Kilho 1.5 0.1 NaN
two 2015.0 Kilho 1.7 0.2 -1.2
three 2016.0 Kilho 3.6 0.3 NaN
four 2015.0 Charles 2.4 0.4 -1.5
five 2016.0 Charles 2.9 0.5 -1.7
six 2013.0 Jun 4.0 0.1 2.1
In [79]:
# .iloc 사용:: index 번호를 사용한다.
df.iloc[3] # 3번째 행을 가져온다.
Out[79]:
Info
year          2015
names      Charles
points         2.4
penalty        0.4
debt          -1.5
Name: four, dtype: object
In [80]:
df.iloc[3:5, 0:2]
Out[80]:
Info year names
Order
four 2015.0 Charles
five 2016.0 Charles
In [81]:
df.iloc[[0,1,3], [1,2]]
Out[81]:
Info names points
Order
one Kilho 1.5
two Kilho 1.7
four Charles 2.4
In [83]:
df.iloc[:,1:4]
Out[83]:
Info names points penalty
Order
one Kilho 1.5 0.1
two Kilho 1.7 0.2
three Kilho 3.6 0.3
four Charles 2.4 0.4
five Charles 2.9 0.5
six Jun 4.0 0.1
In [84]:
df.iloc[1,1]
Out[84]:
'Kilho'

4. DataFrame에서의 boolean Indexing

In [85]:
df
Out[85]:
Info year names points penalty debt
Order
one 2014.0 Kilho 1.5 0.1 NaN
two 2015.0 Kilho 1.7 0.2 -1.2
three 2016.0 Kilho 3.6 0.3 NaN
four 2015.0 Charles 2.4 0.4 -1.5
five 2016.0 Charles 2.9 0.5 -1.7
six 2013.0 Jun 4.0 0.1 2.1
In [87]:
# year가 2014보다 큰 boolean data
df['year'] > 2014
Out[87]:
Order
one      False
two       True
three     True
four      True
five      True
six      False
Name: year, dtype: bool
In [89]:
# year가 2014보다 큰 모든 행의 값
df.loc[df['year']>2014,:]
Out[89]:
Info year names points penalty debt
Order
two 2015.0 Kilho 1.7 0.2 -1.2
three 2016.0 Kilho 3.6 0.3 NaN
four 2015.0 Charles 2.4 0.4 -1.5
five 2016.0 Charles 2.9 0.5 -1.7
In [90]:
df.loc[df['names'] == 'Kilho',['names','points']]
Out[90]:
Info names points
Order
one Kilho 1.5
two Kilho 1.7
three Kilho 3.6
In [92]:
# numpy에서와 같이 논리연산을 응용할 수 있다.
df.loc[(df['points']>2)&(df['points']<3),:]
Out[92]:
Info year names points penalty debt
Order
four 2015.0 Charles 2.4 0.4 -1.5
five 2016.0 Charles 2.9 0.5 -1.7
In [93]:
# 새로운 값을 대입할 수도 있다.
df.loc[df['points'] > 3, 'penalty'] = 0
In [94]:
df
Out[94]:
Info year names points penalty debt
Order
one 2014.0 Kilho 1.5 0.1 NaN
two 2015.0 Kilho 1.7 0.2 -1.2
three 2016.0 Kilho 3.6 0.0 NaN
four 2015.0 Charles 2.4 0.4 -1.5
five 2016.0 Charles 2.9 0.5 -1.7
six 2013.0 Jun 4.0 0.0 2.1

5. Data

In [95]:
# DataFrame을 만들때 index, column을 설정하지 않으면 기본값으로 0부터 시작하는 정수형 숫자로 입력된다.
df = pd.DataFrame(np.random.randn(6,4))
df
Out[95]:
0 1 2 3
0 0.682000 -0.570393 -1.602829 -1.316469
1 -1.176203 0.171527 0.387018 1.027615
2 -0.263178 -0.212049 1.006856 0.096111
3 2.679378 0.347145 0.548144 0.826258
4 -0.249877 0.018721 -0.393715 0.302361
5 0.851420 -0.440360 -0.345895 1.055936
In [98]:
df.columns = ['A', 'B', 'C', 'D']
df.index = pd.date_range('20160701', periods=6)
#pandas에서 제공하는 date range함수는 datetime 자료형으로 구성된, 날짜 시각등을 알 수 있는 자료형을 만드는 함수
df.index
Out[98]:
DatetimeIndex(['2016-07-01', '2016-07-02', '2016-07-03', '2016-07-04',
               '2016-07-05', '2016-07-06'],
              dtype='datetime64[ns]', freq='D')
In [99]:
df
Out[99]:
A B C D
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469
2016-07-02 -1.176203 0.171527 0.387018 1.027615
2016-07-03 -0.263178 -0.212049 1.006856 0.096111
2016-07-04 2.679378 0.347145 0.548144 0.826258
2016-07-05 -0.249877 0.018721 -0.393715 0.302361
2016-07-06 0.851420 -0.440360 -0.345895 1.055936
In [101]:
# np.nan은 NaN값을 의미한다.
df['F'] = [1.0, np.nan, 3.5, 6.1, np.nan, 7.0]
df
Out[101]:
A B C D F
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469 1.0
2016-07-02 -1.176203 0.171527 0.387018 1.027615 NaN
2016-07-03 -0.263178 -0.212049 1.006856 0.096111 3.5
2016-07-04 2.679378 0.347145 0.548144 0.826258 6.1
2016-07-05 -0.249877 0.018721 -0.393715 0.302361 NaN
2016-07-06 0.851420 -0.440360 -0.345895 1.055936 7.0

NaN 없애기

In [102]:
# 행의 값중 하나라도 nan인 경우 그 행을 없앤다.
df.dropna(how='any') 
Out[102]:
A B C D F
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469 1.0
2016-07-03 -0.263178 -0.212049 1.006856 0.096111 3.5
2016-07-04 2.679378 0.347145 0.548144 0.826258 6.1
2016-07-06 0.851420 -0.440360 -0.345895 1.055936 7.0
In [103]:
# 행의 값의 모든 값이 nan인 경우 그 행으 없앤다.
df.dropna(how='all')
Out[103]:
A B C D F
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469 1.0
2016-07-02 -1.176203 0.171527 0.387018 1.027615 NaN
2016-07-03 -0.263178 -0.212049 1.006856 0.096111 3.5
2016-07-04 2.679378 0.347145 0.548144 0.826258 6.1
2016-07-05 -0.249877 0.018721 -0.393715 0.302361 NaN
2016-07-06 0.851420 -0.440360 -0.345895 1.055936 7.0

주의 drop함수는 특정 행 또는 열을 drop하고난 DataFrame을 반환한다.

즉, 반환을 받지 않으면 기존의 DataFrame은 그대로이다.

아니면, inplace=True라는 인자를 추가하여, 반환을 받지 않고서도

기존의 DataFrame이 변경되도록 한다.

In [104]:
# nan값에 값 넣기
df.fillna(value=0.5)
Out[104]:
A B C D F
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469 1.0
2016-07-02 -1.176203 0.171527 0.387018 1.027615 0.5
2016-07-03 -0.263178 -0.212049 1.006856 0.096111 3.5
2016-07-04 2.679378 0.347145 0.548144 0.826258 6.1
2016-07-05 -0.249877 0.018721 -0.393715 0.302361 0.5
2016-07-06 0.851420 -0.440360 -0.345895 1.055936 7.0
In [107]:
# nan값인지 확인하기
df.isnull()
Out[107]:
A B C D F
2016-07-01 False False False False False
2016-07-02 False False False False True
2016-07-03 False False False False False
2016-07-04 False False False False False
2016-07-05 False False False False True
2016-07-06 False False False False False
In [109]:
# F열에서 nan값을 포함하는 행만 추출하기
df.loc[df.isnull()['F'],:]
Out[109]:
A B C D F
2016-07-02 -1.176203 0.171527 0.387018 1.027615 NaN
2016-07-05 -0.249877 0.018721 -0.393715 0.302361 NaN
In [110]:
pd.to_datetime('20160701')
Out[110]:
Timestamp('2016-07-01 00:00:00')
In [111]:
# 특정 행 drop하기
df.drop(pd.to_datetime('20160701'))
Out[111]:
A B C D F
2016-07-02 -1.176203 0.171527 0.387018 1.027615 NaN
2016-07-03 -0.263178 -0.212049 1.006856 0.096111 3.5
2016-07-04 2.679378 0.347145 0.548144 0.826258 6.1
2016-07-05 -0.249877 0.018721 -0.393715 0.302361 NaN
2016-07-06 0.851420 -0.440360 -0.345895 1.055936 7.0
In [112]:
# 2개 이상도 가능
df.drop([pd.to_datetime('20160702'),pd.to_datetime('20160704')])
Out[112]:
A B C D F
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469 1.0
2016-07-03 -0.263178 -0.212049 1.006856 0.096111 3.5
2016-07-05 -0.249877 0.018721 -0.393715 0.302361 NaN
2016-07-06 0.851420 -0.440360 -0.345895 1.055936 7.0
In [113]:
# 특정 열 삭제하기
df.drop('F', axis = 1)
Out[113]:
A B C D
2016-07-01 0.682000 -0.570393 -1.602829 -1.316469
2016-07-02 -1.176203 0.171527 0.387018 1.027615
2016-07-03 -0.263178 -0.212049 1.006856 0.096111
2016-07-04 2.679378 0.347145 0.548144 0.826258
2016-07-05 -0.249877 0.018721 -0.393715 0.302361
2016-07-06 0.851420 -0.440360 -0.345895 1.055936
In [114]:
# 2개 이상의 열도 가능
df.drop(['B','D'], axis = 1)
Out[114]:
A C F
2016-07-01 0.682000 -1.602829 1.0
2016-07-02 -1.176203 0.387018 NaN
2016-07-03 -0.263178 1.006856 3.5
2016-07-04 2.679378 0.548144 6.1
2016-07-05 -0.249877 -0.393715 NaN
2016-07-06 0.851420 -0.345895 7.0

6. Data 분석용 함수들

In [115]:
data = [[1.4, np.nan],
           [7.1, -4.5],
        [np.nan, np.nan],
        [0.75, -1.3]]
df = pd.DataFrame(data, columns=["one", "two"], index=["a", "b", "c", "d"])
In [116]:
df
Out[116]:
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
In [118]:
# 행방향으로의 합(즉, 각 열의 합)
df.sum(axis=0)
Out[118]:
one    9.25
two   -5.80
dtype: float64
In [119]:
# 열방향으로의 합(즉, 각 행의 합)
df.sum(axis=1)
Out[119]:
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64

이때, 위에서 볼 수 있듯이 NaN값은 배제하고 계산한다.

NaN 값을 배제하지 않고 계산하려면 아래와 같이 skipna에 대해 false를 지정해준다.

In [123]:
df.sum(axis=1, skipna=False)
Out[123]:
a     NaN
b    2.60
c     NaN
d   -0.55
dtype: float64
In [120]:
# 특정 행 또는 특정 열에서만 계산하기
df['one'].sum()
Out[120]:
9.25
In [121]:
df.loc['b'].sum()
Out[121]:
2.5999999999999996

pandas에서 DataFrame에 적용되는 함수들

sum() 함수 이외에도 pandas에서 DataFrame에 적용되는 함수는 다음의 것들이 있다.

count 전체 성분의 (NaN이 아닌) 값의 갯수를 계산

min, max 전체 성분의 최솟, 최댓값을 계산

argmin, argmax 전체 성분의 최솟값, 최댓값이 위치한 (정수)인덱스를 반환

idxmin, idxmax 전체 인덱스 중 최솟값, 최댓값을 반환

quantile 전체 성분의 특정 사분위수에 해당하는 값을 반환 (0~1 사이)

sum 전체 성분의 합을 계산

mean 전체 성분의 평균을 계산

median 전체 성분의 중간값을 반환

mad 전체 성분의 평균값으로부터의 절대 편차(absolute deviation)의 평균을 계산

std, var 전체 성분의 표준편차, 분산을 계산

cumsum 맨 첫 번째 성분부터 각 성분까지의 누적합을 계산 (0에서부터 계속 더해짐)

cumprod 맨 첫번째 성분부터 각 성분까지의 누적곱을 계산 (1에서부터 계속 곱해짐)

In [125]:
df2 = pd.DataFrame(np.random.randn(6, 4),
                   columns=["A", "B", "C", "D"],
                   index=pd.date_range("20160701", periods=6))
df2
Out[125]:
A B C D
2016-07-01 1.024359 0.213159 0.277114 -0.304599
2016-07-02 -1.693934 0.619885 -1.620676 0.067814
2016-07-03 -0.216422 0.659557 0.342833 -0.141637
2016-07-04 -0.873492 0.669932 -0.515944 0.280424
2016-07-05 -0.923094 -1.174652 2.678657 -0.663322
2016-07-06 -1.580576 0.539906 -1.900090 -0.428551
In [127]:
# A열과 B열의 상관계수 구하기
df2['A'].corr(df2['B'])
Out[127]:
-0.06715327766901227
In [128]:
# B열과 C열의 공분산 구하기
df2['B'].cov(df2['C'])
Out[128]:
-1.0099019967454226

정렬함수 및 기타함수

In [130]:
dates = df2.index
random_dates = np.random.permutation(dates)
df2 = df2.reindex(index=random_dates, columns=["D", "B", "C", "A"])
df2
Out[130]:
D B C A
2016-07-02 0.067814 0.619885 -1.620676 -1.693934
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576
2016-07-03 -0.141637 0.659557 0.342833 -0.216422
2016-07-01 -0.304599 0.213159 0.277114 1.024359
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094
2016-07-04 0.280424 0.669932 -0.515944 -0.873492
In [131]:
# index와 column의 순서가 섞여있다.
# 이때 index가 오름차순이 되도록 정렬해보자
df2.sort_index(axis=0)
Out[131]:
D B C A
2016-07-01 -0.304599 0.213159 0.277114 1.024359
2016-07-02 0.067814 0.619885 -1.620676 -1.693934
2016-07-03 -0.141637 0.659557 0.342833 -0.216422
2016-07-04 0.280424 0.669932 -0.515944 -0.873492
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576
In [132]:
# column을 기준으로?
df2.sort_index(axis=1)
Out[132]:
A B C D
2016-07-02 -1.693934 0.619885 -1.620676 0.067814
2016-07-06 -1.580576 0.539906 -1.900090 -0.428551
2016-07-03 -0.216422 0.659557 0.342833 -0.141637
2016-07-01 1.024359 0.213159 0.277114 -0.304599
2016-07-05 -0.923094 -1.174652 2.678657 -0.663322
2016-07-04 -0.873492 0.669932 -0.515944 0.280424
In [134]:
# 내림차순으로는?
df2.sort_index(axis=1, ascending=False)
Out[134]:
D C B A
2016-07-02 0.067814 -1.620676 0.619885 -1.693934
2016-07-06 -0.428551 -1.900090 0.539906 -1.580576
2016-07-03 -0.141637 0.342833 0.659557 -0.216422
2016-07-01 -0.304599 0.277114 0.213159 1.024359
2016-07-05 -0.663322 2.678657 -1.174652 -0.923094
2016-07-04 0.280424 -0.515944 0.669932 -0.873492
In [135]:
# 값 기준 정렬하기
# D열의 값이 오름차순이 되도록 정렬하기
df2.sort_values(by='D')
Out[135]:
D B C A
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576
2016-07-01 -0.304599 0.213159 0.277114 1.024359
2016-07-03 -0.141637 0.659557 0.342833 -0.216422
2016-07-02 0.067814 0.619885 -1.620676 -1.693934
2016-07-04 0.280424 0.669932 -0.515944 -0.873492
In [136]:
# B열의 값이 내림차순이 되도록 정렬하기
df2.sort_values(by='B', ascending=False)
Out[136]:
D B C A
2016-07-04 0.280424 0.669932 -0.515944 -0.873492
2016-07-03 -0.141637 0.659557 0.342833 -0.216422
2016-07-02 0.067814 0.619885 -1.620676 -1.693934
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576
2016-07-01 -0.304599 0.213159 0.277114 1.024359
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094
In [138]:
df2["E"] = np.random.randint(0, 6, size=6)
df2["F"] = ["alpha", "beta", "gamma", "gamma", "alpha", "gamma"]
df2
Out[138]:
D B C A E F
2016-07-02 0.067814 0.619885 -1.620676 -1.693934 1 alpha
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576 1 beta
2016-07-03 -0.141637 0.659557 0.342833 -0.216422 3 gamma
2016-07-01 -0.304599 0.213159 0.277114 1.024359 4 gamma
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094 5 alpha
2016-07-04 0.280424 0.669932 -0.515944 -0.873492 0 gamma
In [139]:
# E열과 F열을 동시에 고려하여, 오름차순으로 하려면?
df2.sort_values(by=['E','F'])
Out[139]:
D B C A E F
2016-07-04 0.280424 0.669932 -0.515944 -0.873492 0 gamma
2016-07-02 0.067814 0.619885 -1.620676 -1.693934 1 alpha
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576 1 beta
2016-07-03 -0.141637 0.659557 0.342833 -0.216422 3 gamma
2016-07-01 -0.304599 0.213159 0.277114 1.024359 4 gamma
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094 5 alpha
In [140]:
# 지정한 행 또는 열에서 중복값을 제외한 유니크한 값만 얻기
df2['F'].unique()
Out[140]:
array(['alpha', 'beta', 'gamma'], dtype=object)
In [142]:
# 지정한 행 또는 열에서 값에 따른 개수 얻기
df2['F'].value_counts()
Out[142]:
gamma    3
alpha    2
beta     1
Name: F, dtype: int64
In [144]:
# 지정한 행 또는 열에서 입력한 값이 있는지 확인하기
df2['F'].isin(['alpha','beta'])
# 아래와 같이 응용할 수 있다.
Out[144]:
2016-07-02     True
2016-07-06     True
2016-07-03    False
2016-07-01    False
2016-07-05     True
2016-07-04    False
Name: F, dtype: bool
In [146]:
# F열의 값이 alpha나 beta인 모든 행 구하기
df2.loc[df2['F'].isin(['alpha','beta']),:]
Out[146]:
D B C A E F
2016-07-02 0.067814 0.619885 -1.620676 -1.693934 1 alpha
2016-07-06 -0.428551 0.539906 -1.900090 -1.580576 1 beta
2016-07-05 -0.663322 -1.174652 2.678657 -0.923094 5 alpha

사용자가 직접 만든 함수를 적용하기

In [149]:
df3 = pd.DataFrame(np.random.randn(4, 3), columns=["b", "d", "e"],
                   index=["Seoul", "Incheon", "Busan", "Daegu"])
df3
Out[149]:
b d e
Seoul 0.806401 -0.101789 -0.201956
Incheon 0.666876 -2.144428 -0.013760
Busan 1.811228 0.225317 1.445495
Daegu -0.608445 0.128199 -0.325935
In [150]:
func = lambda x: x.max() - x.min()
In [151]:
df3.apply(func, axis=0)
Out[151]:
b    2.419673
d    2.369745
e    1.771431
dtype: float64

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

Numpy_clear


안녕하세요. 문범우입니다.

이번 포스팅에서는 python을 통해 데이터 분석을 할때 기초 라이브러리로 사용되는 Numpy에 대해서 알아보도록 하겠습니다.


해당 내용은 flearning의 김길호님의 강의를 바탕으로 작성되었습니다.

https://www.flearning.net/courses/6



1. Numpy란


Numpy는 C언어로 구현된 파이썬 라이브러리로써, 고성능의 수치계산을 위해 제작되었습니다. Numerical Python의 줄임말이기도 한 Numpy는 벡터 및 행렬 연산에 있어서 매우 편리한 기능을 제공합니다.

또한 이는 데이터분석을 할 때 사용되는 라이브러리인 pandas와 matplotlib의 기반으로 사용되기도 합니다.

numpy에서는 기본적으로 array라는 단위로 데이터를 관리하며 이에 대해 연산을 수행합니다. array는 말그대로 행렬이라는 개념으로 생각하시면 됩니다.


먼저 numpy를 사용하기 위해서는 아래와 같은 코드로 numpy를 import해야 합니다.


import numpy as np


사실상, numpy를 설치하고 단순히 import numpy 만 해도 되지만, 이를 코드에서 보다 편하게 사용하기 위해 as np 를 붙임으로써 np라는 이름으로 numpy를 사용합니다.


아래 실습에서는 jupyter notebook을 사용하였습니다.

Numpy 기초

1. Numpy 란?

In [1]:
# numpy 사용하기
import numpy as np

2. Array 정의 및 사용하기

In [2]:
data1 = [1,2,3,4,5]
data1
Out[2]:
[1, 2, 3, 4, 5]
In [3]:
data2 = [1,2,3,3.5,4]
data2
Out[3]:
[1, 2, 3, 3.5, 4]
In [4]:
# numpy를 이용하여 array 정의하기
# 1. 위에서 만든 python list를 이용
arr1 = np.array(data1)
arr1
Out[4]:
array([1, 2, 3, 4, 5])
In [5]:
# array의 형태(크기)를 확인할 수 있다.
arr1.shape
Out[5]:
(5,)
In [6]:
# 2. 바로 python list를 넣어 줌으로써 만들기
arr2 = np.array([1,2,3,4,5])
arr2
Out[6]:
array([1, 2, 3, 4, 5])
In [7]:
arr2.shape
Out[7]:
(5,)
In [8]:
# array의 자료형을 확인할 수 있다.
arr2.dtype
Out[8]:
dtype('int64')
In [9]:
arr3 = np.array(data2)
arr3
Out[9]:
array([1. , 2. , 3. , 3.5, 4. ])
In [11]:
arr3.shape
Out[11]:
(5,)
In [12]:
arr3.dtype
Out[12]:
dtype('float64')
In [21]:
arr4 = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
arr4
Out[21]:
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])
In [22]:
arr4.shape
Out[22]:
(4, 3)

numpy shape

numpy에서는 해당 array의 크기를 알 수 있다.

shape 을 확인함으로써 몇개의 데이터가 있는지, 몇 차원으로 존재하는지 등을 확인할 수 있다.

위에서 arr1.shape의 결과는 (5,) 으로써, 1차원의 데이터이며 총 5라는 크기를 갖고 있음을 알 수 있다.

arr4.shape의 결과는 (4,3) 으로써, 2차원의 데이터이며 4 * 3 크기를 갖고 있는 array 이다.

numpy 자료형

arr1이나 arr2는 int64라는 자료형을 갖는 것에 반해 arr3는 float64라는 자료형을 갖는다.

이는 arr3내부 데이터를 살펴보면 3.5라는 실수형 데이터를 갖기 때문임을 알 수 있다.

numpy에서 사용되는 자료형은 아래와 같다. (자료형 뒤에 붙는 숫자는 몇 비트 크기인지를 의미한다.)

  • 부호가 있는 정수 int(8, 16, 32, 64)
  • 부호가 없는 정수 uint(8 ,16, 32, 54)
  • 실수 float(16, 32, 64, 128)
  • 복소수 complex(64, 128, 256)
  • 불리언 bool
  • 문자열 string_
  • 파이썬 오프젝트 object
  • 유니코드 unicode_

2-1. np.zeros(), np.ones(), np.arange() 함수

numpy에서 array를 정의할 때 사용되는 함수들이다.

아래 실습을 통해 각각이 어떻게 다른지 살펴본다.

In [23]:
np.zeros(10)
Out[23]:
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [25]:
np.zeros((3,5))
Out[25]:
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
In [24]:
# np.zeros() 함수는 인자로 받는 크기만큼, 모든요소가 0인 array를 만든다.
In [26]:
np.ones(9)
Out[26]:
array([1., 1., 1., 1., 1., 1., 1., 1., 1.])
In [27]:
np.ones((2,10))
Out[27]:
array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
In [28]:
# np.ones() 함수는 인자로 받는 크기만큼, 모든요소가 1인 array를 만든다.
In [29]:
np.arange(10)
Out[29]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [32]:
np.arange(3,10)
Out[32]:
array([3, 4, 5, 6, 7, 8, 9])
In [33]:
# np.arange() 함수는 인자로 받는 값 만큼 1씩 증가하는 1차원 array를 만든다.
# 이때 하나의 인자만 입력하면 0 ~ 입력한 인자, 값 만큼의 크기를 가진다.

3. Array 연산

기본적으로 numpy에서 연산을 할때는 크기가 서로 동일한 array 끼리 연산이 진행된다.

이때 같은 위치에 있는 요소들 끼리 연산이 진행된다.

In [40]:
arr1 = np.array([[1,2,3],[4,5,6]])
arr1
Out[40]:
array([[1, 2, 3],
       [4, 5, 6]])
In [41]:
arr1.shape
Out[41]:
(2, 3)
In [42]:
arr2 = np.array([[10,11,12],[13,14,15]])
arr2
Out[42]:
array([[10, 11, 12],
       [13, 14, 15]])
In [43]:
arr2.shape
Out[43]:
(2, 3)

3-1. array 덧셈

In [44]:
arr1 + arr2
Out[44]:
array([[11, 13, 15],
       [17, 19, 21]])

3-2. array 뺄셈

In [45]:
arr1 - arr2
Out[45]:
array([[-9, -9, -9],
       [-9, -9, -9]])

3-3. array 곱셈

주의하자.

행렬의 곱처럼 곱셈이 진행되는 것이 아니라 각 요소별로 곱셈이 진행된다.

In [47]:
arr1 * arr2
Out[47]:
array([[10, 22, 36],
       [52, 70, 90]])

3-4. array 나눗셈

In [48]:
arr1 / arr2
Out[48]:
array([[0.1       , 0.18181818, 0.25      ],
       [0.30769231, 0.35714286, 0.4       ]])

3-5. array의 브로드 캐스트

위에서는 array가 같은 크기를 가져야 서로 연산이 가능하다고 했지만,

numpy에서는 브로드캐스트라는 기능을 제공한다.

브로드캐스트란, 서로 크기가 다른 array가 연산이 가능하게끔 하는 것이다.

In [49]:
arr1
Out[49]:
array([[1, 2, 3],
       [4, 5, 6]])
In [50]:
arr1.shape
Out[50]:
(2, 3)
In [52]:
arr3 = np.array([10,11,12])
arr3
Out[52]:
array([10, 11, 12])
In [53]:
arr3.shape
Out[53]:
(3,)
In [54]:
arr1 + arr3
Out[54]:
array([[11, 13, 15],
       [14, 16, 18]])
In [55]:
arr1 * arr3
Out[55]:
array([[10, 22, 36],
       [40, 55, 72]])

위와 같이 서로 크기가 다른 arr1과 arr3의 연산이 가능하다.

연산결과를 살펴보면 arr3이 [10,11,12] 에서 [[10,11,12],[10,11,12]]로 확장되어 계산되었음을 확인할 수 있다.

동일한 방식으로 하나의 array에 스칼라 연산도 가능하다.

In [56]:
arr1 * 10
Out[56]:
array([[10, 20, 30],
       [40, 50, 60]])
In [57]:
# 요소에 대해 제곱처리
arr1 ** 2
Out[57]:
array([[ 1,  4,  9],
       [16, 25, 36]])

4. Array 인덱싱

numpy에서 사용되는 인덱싱은 기본적으로 python 인덱싱과 동일하다.

이때, python에서와 같이 1번째로 시작하는 것이 아니라 0번째로 시작하는 것에 주의한다.

In [64]:
arr1 = np.arange(10)
arr1
Out[64]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [65]:
# 0번째 요소
arr1[0]
Out[65]:
0
In [66]:
# 3번째 요소
arr1[3]
Out[66]:
3
In [72]:
# 3번째 요소부터 8번째 요소
arr1[3:9]
Out[72]:
array([3, 4, 5, 6, 7, 8])
In [73]:
arr1[:]
Out[73]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

물론 1차원이 아닌 그 이상의 차원에서도 인덱싱이 가능하다.

In [69]:
arr2 = np.array([[1,2,3,4],
                 [5,6,7,8],
                 [9,10,11,12]])
arr2
Out[69]:
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
In [71]:
# 2차원의 array에서 인덱싱을 하기 위해선 2개의 인자를 입력해야 합니다.
arr2[0,0]
Out[71]:
1
In [77]:
# 2행의 모든 요소 꺼내기
arr2[2,:]
Out[77]:
array([ 9, 10, 11, 12])
In [78]:
# 2행의 3번째 요소 꺼내기
arr2[2,3]
Out[78]:
12
In [80]:
# 모든 열의 3번째 요소 꺼내기
arr2[:,3]
Out[80]:
array([ 4,  8, 12])

5. Array boolean 인덱싱(마스크)

위에서 이용한 다차원의 인덱싱을 응용하여 boolean 인덱싱을 할 수 있다.

해당 기능은 주로 마스크라고 이야기하는데, boolean인덱싱을 통해 만들어낸 array를 통해

우리가 원하는 행 또는 열의 값만 뽑아낼 수 있다.

즉, 마스크처럼 우리가 가리고 싶은 부분은 가리고, 원하는 요소만 꺼낼 수 있다.

In [81]:
names = np.array(['Beomwoo','Beomwoo','Kim','Joan','Lee','Beomwoo','Park','Beomwoo'])
names
Out[81]:
array(['Beomwoo', 'Beomwoo', 'Kim', 'Joan', 'Lee', 'Beomwoo', 'Park',
       'Beomwoo'], dtype='<U7')
In [82]:
names.shape
Out[82]:
(8,)
In [87]:
# 아래에서 사용되는 np.random.randn() 함수는 기대값이 0이고, 표준편차가 1인 가우시안 정규 분포를 따르는 난수를 발생시키는 함수이다.
# 이 외에도 0~1의 난수를 발생시키는 np.random.rand() 함수도 존재한다.
data = np.random.randn(8,4)
data
Out[87]:
array([[-1.07099572, -0.85382063, -1.42474621, -0.05992846],
       [ 1.93097843, -1.8885167 ,  1.99767454,  0.31524498],
       [-0.22633642, -0.76385264,  0.16368804,  0.91204438],
       [ 1.34321923,  1.54532121,  0.28814921,  0.50688776],
       [ 0.4126606 , -0.52356522,  0.27124037, -0.66383264],
       [ 0.88575452, -1.39205929,  0.91019739, -1.04676349],
       [-0.05673648, -1.63408607, -2.29844338, -0.3662913 ],
       [ 0.45963024,  0.35662128,  0.18307525,  1.46992167]])
In [88]:
data.shape
Out[88]:
(8, 4)

위와 같은 names와 data라는 array가 있다.

이때, names의 각 요소가 data의 각 행과 연결된다고 가정해보자.

그리고 이 때, names가 Beomwoo인 행의 data만 보고 싶을 때 다음과 같이 마스크를 사용한다.

In [91]:
# 요소가 Beomwoo인 항목에 대한 mask 생성
names_Beomwoo_mask = (names == 'Beomwoo')
names_Beomwoo_mask
Out[91]:
array([ True,  True, False, False, False,  True, False,  True])
In [92]:
data[names_Beomwoo_mask,:]
Out[92]:
array([[-1.07099572, -0.85382063, -1.42474621, -0.05992846],
       [ 1.93097843, -1.8885167 ,  1.99767454,  0.31524498],
       [ 0.88575452, -1.39205929,  0.91019739, -1.04676349],
       [ 0.45963024,  0.35662128,  0.18307525,  1.46992167]])

위의 결과를 보면, 요소가 Beomwoo인 것은 0번째, 1번째, 5번째, 7번째 이므로

data에서 0,1,5,7행의 모든 요소를 꺼내와야 한다.

이를 위해 요소가 Beomwoo인 것에 대한 boolean 값을 가지는 mask를 만들었고

마스크를 인덱싱에 응용하여 data의 0,1,5,7행을 꺼냈다.

In [93]:
# 요소가 Kim인 행의 데이터만 꺼내기
data[names == 'Kim',:]
Out[93]:
array([[-0.22633642, -0.76385264,  0.16368804,  0.91204438]])
In [94]:
# 논리 연산을 응용하여, 요소가 Kim 또는 Park인 행의 데이터만 꺼내기
data[(names == 'Kim') | (names == 'Park'),:]
Out[94]:
array([[-0.22633642, -0.76385264,  0.16368804,  0.91204438],
       [-0.05673648, -1.63408607, -2.29844338, -0.3662913 ]])

물론 data array 자체적으로도 마스크를 만들고, 이를 응용하여 인덱싱이 가능하다.

data array에서 0번째 열의 값이 0보다 작은 행을 구해보자.

In [97]:
# 먼저 마스크를 만든다.
# data array에서 0번째 열이 0보다 작은 요소의 boolean 값은 다음과 같다.
data[:,0] < 0
Out[97]:
array([ True, False,  True, False, False, False,  True, False])
In [98]:
# 위에서 만든 마스크를 이용하여 0번째 열의 값이 0보다 작은 행을 구한다.
data[data[:,0]<0,:]
Out[98]:
array([[-1.07099572, -0.85382063, -1.42474621, -0.05992846],
       [-0.22633642, -0.76385264,  0.16368804,  0.91204438],
       [-0.05673648, -1.63408607, -2.29844338, -0.3662913 ]])

이를 통해 특정 위치에만 우리가 원하는 값을 대입할 수 있다.

위에서 얻은, 0번째 열의 값이 0보다 작은 행의 2,3번째 열값에 0을 대입해보자.

In [100]:
# 0번째 열의 값이 0보다 작은 행의 2,3번째 열 값
data[data[:,0]<0,2:4]
Out[100]:
array([[-1.42474621, -0.05992846],
       [ 0.16368804,  0.91204438],
       [-2.29844338, -0.3662913 ]])
In [102]:
data[data[:,0]<0,2:4] = 0
data
Out[102]:
array([[-1.07099572, -0.85382063,  0.        ,  0.        ],
       [ 1.93097843, -1.8885167 ,  1.99767454,  0.31524498],
       [-0.22633642, -0.76385264,  0.        ,  0.        ],
       [ 1.34321923,  1.54532121,  0.28814921,  0.50688776],
       [ 0.4126606 , -0.52356522,  0.27124037, -0.66383264],
       [ 0.88575452, -1.39205929,  0.91019739, -1.04676349],
       [-0.05673648, -1.63408607,  0.        ,  0.        ],
       [ 0.45963024,  0.35662128,  0.18307525,  1.46992167]])

6. Numpy 함수

numpy에서는 array에 적용되는 다양한 함수가 있다.

6-1. 하나의 array에 적용되는 함수

In [112]:
arr1 = np.random.randn(5,3)
arr1
Out[112]:
array([[-1.28394941, -1.38235479,  0.3676742 ],
       [ 0.91707237,  0.45364032,  0.00683315],
       [ 0.51191795,  0.39014894, -0.15396686],
       [ 0.75541648, -3.0457677 ,  0.83785171],
       [ 0.36609986,  1.2300834 ,  0.51764117]])
In [113]:
# 각 성분의 절대값 계산하기
np.abs(arr1)
Out[113]:
array([[1.28394941, 1.38235479, 0.3676742 ],
       [0.91707237, 0.45364032, 0.00683315],
       [0.51191795, 0.39014894, 0.15396686],
       [0.75541648, 3.0457677 , 0.83785171],
       [0.36609986, 1.2300834 , 0.51764117]])
In [114]:
# 각 성분의 제곱근 계산하기 ( == array ** 0.5)
np.sqrt(arr1)
/Users/doorbw/anaconda3/envs/tensorflow/lib/python3.6/site-packages/ipykernel/__main__.py:2: RuntimeWarning: invalid value encountered in sqrt
  from ipykernel import kernelapp as app
Out[114]:
array([[       nan,        nan, 0.60636144],
       [0.95763896, 0.67352826, 0.08266285],
       [0.71548442, 0.62461903,        nan],
       [0.86914699,        nan, 0.9153424 ],
       [0.60506187, 1.10909125, 0.71947284]])
In [115]:
# 각 성분의 제곱 계산하기
np.square(arr1)
Out[115]:
array([[1.64852609e+00, 1.91090476e+00, 1.35184315e-01],
       [8.41021739e-01, 2.05789543e-01, 4.66919060e-05],
       [2.62059989e-01, 1.52216194e-01, 2.37057951e-02],
       [5.70654061e-01, 9.27670091e+00, 7.01995494e-01],
       [1.34029109e-01, 1.51310516e+00, 2.67952378e-01]])
In [116]:
# 각 성분을 무리수 e의 지수로 삼은 값을 계산하기
np.exp(arr1)
Out[116]:
array([[0.27694138, 0.25098684, 1.44437138],
       [2.50195487, 1.57403175, 1.00685655],
       [1.66848821, 1.47720079, 0.85730043],
       [2.12849782, 0.04755979, 2.3113961 ],
       [1.44209925, 3.42151487, 1.6780647 ]])
In [117]:
# 각 성분을 자연로그, 상용로그, 밑이 2인 로그를 씌운 값을 계산하기
np.log(arr1)
/Users/doorbw/anaconda3/envs/tensorflow/lib/python3.6/site-packages/ipykernel/__main__.py:2: RuntimeWarning: invalid value encountered in log
  from ipykernel import kernelapp as app
Out[117]:
array([[        nan,         nan, -1.00055807],
       [-0.08656889, -0.79045064, -4.98596986],
       [-0.66959092, -0.94122672,         nan],
       [-0.28048605,         nan, -0.17691415],
       [-1.00484914,  0.20708197, -0.65847301]])
In [118]:
np.log10(arr1)
/Users/doorbw/anaconda3/envs/tensorflow/lib/python3.6/site-packages/ipykernel/__main__.py:1: RuntimeWarning: invalid value encountered in log10
  if __name__ == '__main__':
Out[118]:
array([[        nan,         nan, -0.43453685],
       [-0.03759639, -0.34328835, -2.1653792 ],
       [-0.29079964, -0.40876957,         nan],
       [-0.12181354,         nan, -0.07683284],
       [-0.43640043,  0.08993456, -0.28597119]])
In [119]:
np.log2(arr1)
/Users/doorbw/anaconda3/envs/tensorflow/lib/python3.6/site-packages/ipykernel/__main__.py:1: RuntimeWarning: invalid value encountered in log2
  if __name__ == '__main__':
Out[119]:
array([[        nan,         nan, -1.44350016],
       [-0.1248925 , -1.14037921, -7.193234  ],
       [-0.9660155 , -1.35790312,         nan],
       [-0.40465583,         nan, -0.25523316],
       [-1.44969086,  0.29875613, -0.94997574]])
In [120]:
# 각 성분의 부호 계산하기(+인 경우 1, -인 경우 -1, 0인 경우 0)
np.sign(arr1)
Out[120]:
array([[-1., -1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1., -1.],
       [ 1., -1.,  1.],
       [ 1.,  1.,  1.]])
In [121]:
# 각 성분의 소수 첫 번째 자리에서 올림한 값을 계산하기
np.ceil(arr1)
Out[121]:
array([[-1., -1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1., -0.],
       [ 1., -3.,  1.],
       [ 1.,  2.,  1.]])
In [122]:
# 각 성분의 소수 첫 번째 자리에서 내림한 값을 계산하기
np.floor(arr1)
Out[122]:
array([[-2., -2.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0., -1.],
       [ 0., -4.,  0.],
       [ 0.,  1.,  0.]])
In [124]:
# 각 성분이 NaN인 경우 True를, 아닌 경우 False를 반환하기
np.isnan(arr1)
Out[124]:
array([[False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False]])
In [125]:
np.isnan(np.log(arr1))
/Users/doorbw/anaconda3/envs/tensorflow/lib/python3.6/site-packages/ipykernel/__main__.py:1: RuntimeWarning: invalid value encountered in log
  if __name__ == '__main__':
Out[125]:
array([[ True,  True, False],
       [False, False, False],
       [False, False,  True],
       [False,  True, False],
       [False, False, False]])
In [126]:
# 각 성분이 무한대인 경우 True를, 아닌 경우 False를 반환하기
np.isinf(arr1)
Out[126]:
array([[False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False]])
In [127]:
# 각 성분에 대해 삼각함수 값을 계산하기(cos, cosh, sin, sinh, tan, tanh)
np.cos(arr1)
Out[127]:
array([[ 0.28292939,  0.18732825,  0.93316587],
       [ 0.60814678,  0.89885772,  0.99997665],
       [ 0.8718066 ,  0.92485242,  0.9881705 ],
       [ 0.72798607, -0.9954123 ,  0.66906099],
       [ 0.9337306 ,  0.33415913,  0.86898882]])
In [128]:
np.tanh(arr1)
Out[128]:
array([[-0.85753362, -0.88147747,  0.35195568],
       [ 0.72450949,  0.42488675,  0.00683304],
       [ 0.47143823,  0.37148862, -0.15276165],
       [ 0.63836924, -0.99548634,  0.68466951],
       [ 0.3505756 ,  0.84260351,  0.47587741]])

6-2. 두 개의 array에 적용되는 함수

In [129]:
arr1
Out[129]:
array([[-1.28394941, -1.38235479,  0.3676742 ],
       [ 0.91707237,  0.45364032,  0.00683315],
       [ 0.51191795,  0.39014894, -0.15396686],
       [ 0.75541648, -3.0457677 ,  0.83785171],
       [ 0.36609986,  1.2300834 ,  0.51764117]])
In [131]:
arr2 = np.random.randn(5,3)
arr2
Out[131]:
array([[-1.08072661,  0.49305711, -1.2341793 ],
       [ 0.72539264, -0.17482108, -2.29144412],
       [ 0.33676285, -0.44206124,  0.68359426],
       [-1.3367298 , -0.62530265,  0.04842608],
       [ 0.46567612, -2.53008109,  0.80771562]])
In [132]:
# 두 개의 array에 대해 동일한 위치의 성분끼리 연산 값을 계산하기(add, subtract, multiply, divide)
np.multiply(arr1,arr2)
Out[132]:
array([[ 1.3875983 , -0.68157986, -0.45377588],
       [ 0.66523755, -0.07930589, -0.01565778],
       [ 0.17239495, -0.17246972, -0.10525086],
       [-1.00978772,  1.90452663,  0.04057388],
       [ 0.17048396, -3.11221075,  0.41810686]])
In [133]:
# 두 개의 array에 대해 동일한 위치의 성분끼리 비교하여 최대값 또는 최소값 계산하기(maximum, minimum)
np.maximum(arr1,arr2)
Out[133]:
array([[-1.08072661,  0.49305711,  0.3676742 ],
       [ 0.91707237,  0.45364032,  0.00683315],
       [ 0.51191795,  0.39014894,  0.68359426],
       [ 0.75541648, -0.62530265,  0.83785171],
       [ 0.46567612,  1.2300834 ,  0.80771562]])

6-3. 통계 함수

통계 함수를 통해 array의 합이나 평균등을 구할 때,

추가로 axis라는 인자에 대한 값을 지정하여 열 또는 행의 합 또는 평균등을 구할 수 있다.

In [134]:
arr1
Out[134]:
array([[-1.28394941, -1.38235479,  0.3676742 ],
       [ 0.91707237,  0.45364032,  0.00683315],
       [ 0.51191795,  0.39014894, -0.15396686],
       [ 0.75541648, -3.0457677 ,  0.83785171],
       [ 0.36609986,  1.2300834 ,  0.51764117]])
In [136]:
# 전체 성분의 합을 계산
np.sum(arr1)
Out[136]:
0.4883407866652476
In [138]:
# 열 간의 합을 계산
np.sum(arr1, axis=1)
Out[138]:
array([-2.29863   ,  1.37754584,  0.74810003, -1.45249951,  2.11382443])
In [140]:
# 행 간의 합을 계산
np.sum(arr1, axis=0)
Out[140]:
array([ 1.26655726, -2.35424983,  1.57603336])
In [141]:
# 전체 성분의 평균을 계산
np.mean(arr1)
Out[141]:
0.032556052444349844
In [142]:
# 행 간의 평균을 계산
np.mean(arr1, axis=0)
Out[142]:
array([ 0.25331145, -0.47084997,  0.31520667])
In [143]:
# 전체 성분의 표준편차, 분산, 최소값, 최대값 계산(std, var, min, max)
np.std(arr1)
Out[143]:
1.0840662273348296
In [145]:
np.min(arr1, axis=1)
Out[145]:
array([-1.38235479,  0.00683315, -0.15396686, -3.0457677 ,  0.36609986])
In [147]:
# 전체 성분의 최소값, 최대값이 위치한 인덱스를 반환(argmin, argmax)
np.argmin(arr1)
Out[147]:
10
In [148]:
np.argmax(arr1,axis=0)
Out[148]:
array([1, 4, 3])
In [149]:
# 맨 처음 성분부터 각 성분까지의 누적합 또는 누적곱을 계산(cumsum, cumprod)
np.cumsum(arr1)
Out[149]:
array([-1.28394941, -2.6663042 , -2.29863   , -1.38155763, -0.92791731,
       -0.92108416, -0.40916621, -0.01901727, -0.17298413,  0.58243235,
       -2.46333535, -1.62548364, -1.25938378, -0.02930038,  0.48834079])
In [152]:
np.cumsum(arr1,axis=1)
Out[152]:
array([[-1.28394941, -2.6663042 , -2.29863   ],
       [ 0.91707237,  1.3707127 ,  1.37754584],
       [ 0.51191795,  0.90206689,  0.74810003],
       [ 0.75541648, -2.29035122, -1.45249951],
       [ 0.36609986,  1.59618326,  2.11382443]])
In [153]:
np.cumprod(arr1)
Out[153]:
array([-1.28394941e+00,  1.77487362e+00,  6.52575230e-01,  5.98458715e-01,
        2.71485005e-01,  1.85509711e-03,  9.49657512e-04,  3.70507870e-04,
       -5.70459347e-05, -4.30934393e-05,  1.31252606e-04,  1.09970221e-04,
        4.02600826e-05,  4.95232591e-05,  2.56352776e-05])

6-4. 기타 함수

In [154]:
arr1
Out[154]:
array([[-1.28394941, -1.38235479,  0.3676742 ],
       [ 0.91707237,  0.45364032,  0.00683315],
       [ 0.51191795,  0.39014894, -0.15396686],
       [ 0.75541648, -3.0457677 ,  0.83785171],
       [ 0.36609986,  1.2300834 ,  0.51764117]])
In [155]:
# 전체 성분에 대해서 오름차순으로 정렬
np.sort(arr1)
Out[155]:
array([[-1.38235479, -1.28394941,  0.3676742 ],
       [ 0.00683315,  0.45364032,  0.91707237],
       [-0.15396686,  0.39014894,  0.51191795],
       [-3.0457677 ,  0.75541648,  0.83785171],
       [ 0.36609986,  0.51764117,  1.2300834 ]])
In [156]:
# 전체 성분에 대해서 내림차순으로 정렬
np.sort(arr1)[::-1]
Out[156]:
array([[ 0.36609986,  0.51764117,  1.2300834 ],
       [-3.0457677 ,  0.75541648,  0.83785171],
       [-0.15396686,  0.39014894,  0.51191795],
       [ 0.00683315,  0.45364032,  0.91707237],
       [-1.38235479, -1.28394941,  0.3676742 ]])
In [157]:
# 행 방향으로 오름차순으로 정렬
np.sort(arr1,axis=0)
Out[157]:
array([[-1.28394941, -3.0457677 , -0.15396686],
       [ 0.36609986, -1.38235479,  0.00683315],
       [ 0.51191795,  0.39014894,  0.3676742 ],
       [ 0.75541648,  0.45364032,  0.51764117],
       [ 0.91707237,  1.2300834 ,  0.83785171]])



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc


안녕하세요. 문범우입니다.


최근 데이터분석, 인공지능 분야에 관심이 있어서 스터디를 시작하여 kaggle문제를 풀어보기 시작했습니다.

개인적으로는 김성훈 교수님의 '모두를 위한 딥러닝'과 '머신러닝 이론 및 파이썬 실습'이라는 온라인 강의를 듣고 바로 도전해보았습니다.


'머신러닝 이론 및 파이썬 실습'에서 타이타닉 문제를 바탕으로 파이썬 실습을 진행하여 해당 내용을 통해 타이타닉 문제에서 어떤식으로 데이터를 보아야 하는지 감을 익혔고 이후 정확도 80%를 목표로 생각하고 진행하였습니다.


어떻게 시작해야 할지 막막하기도 했지만 이것저것 해보고, 아래의 사이트도 참고하면서 코드를 작성하였습니다.

https://towardsdatascience.com/how-i-got-a-score-of-82-3-and-ended-up-being-in-top-4-of-kaggles-titanic-dataset-bb2875cee6b5


아직 부족한 점이 많아서, 오히려 정확도에 악영향을 미친 부분이나 애매한 부분들이 있을 수 있지만 처음 kaggle문제에 도전하시는 분들께서도 참고하시면 좋을 듯하여 나름 코드를 정리하여 포스팅하게 되었습니다.


아래에서 소개해드리는 코드는 다음 사진과 같이 Kaggle에서 80.3%의 정확도를 내었습니다.



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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
# coding: utf-8
 
# In[1]:
 
 
import pandas as pd
 
train = pd.read_csv('input/train.csv')
test = pd.read_csv('input/test.csv')
 
 
# PassengerId 는 필요없다.
# Sex 는 남/여 로 구분, 의미있는 정보라고 생각.
# Nam 은 어떻게 나눌 수 있을까?
# Pclass, Cabin 좌석별로 살 수 있는 차이가 확연히 날 것이라고 판단된다.
# -> 과연? 침몰시간에 사람들이 모두 자신들의 좌석에 있었다는 확신이 부족하다. 침몰시간을 살펴보자.
# Fare? 흠
# Embarked 어디서 탔는지.. 충분히 고려해볼만한 정보일 것
# 남은건, Age, SibSp, Parch
 
# In[2]:
 
 
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib''inline')
import seaborn as sns
sns.set() #setting seaborn default for plots
 
 
# ### age에서 nan값을 채워줘야하는데, nan값을 가진 사람들의 특징을 고려해보아야 하지 않을까?
 
# In[3]:
 
 
age_nan_rows = train[train['Age'].isnull()]
 
 
# In[4]:
 
 
age_nan_rows.head()
 
 
# ### 먼저 가장 간단한 성별을 0,1로 표시
 
# In[5]:
 
 
from sklearn.preprocessing import LabelEncoder
train['Sex'= LabelEncoder().fit_transform(train['Sex'])
test['Sex'= LabelEncoder().fit_transform(test['Sex'])
 
 
# In[6]:
 
 
train.head(10)
 
 
# In[7]:
 
 
test.head()
 
 
# ### 이름의 뒷부분을 고려하기엔 케이스가 너무 많아진다. 이름에서 앞의 성만 따서 생각해보자.
 
# In[8]:
 
 
train['Name'= train['Name'].map(lambda x: x.split(',')[1].split('.')[0].strip())
titles = train['Name'].unique()
titles
test['Name'= test['Name'].map(lambda x: x.split(',')[1].split('.')[0].strip())
test_titles = test['Name'].unique()
test_titles
 
 
# In[9]:
 
 
titles
 
 
# In[10]:
 
 
test_titles
 
 
# ### 나이의 nan값을 채워주기 위해서, 이름의 성별로 중간값을 구하자.
# 남자별, 여자별로 나누어도 좋지만 성별로 하는 것이 더 정확하지 않을까?
# 하지만 성별로 나누는 것도 정확한 기준이 부족하다. 해당 부분에 대해서 좀 더 생각해볼 필요가 있다.
 
# In[11]:
 
 
train['Age'].fillna(-1, inplace=True)
test['Age'].fillna(-1, inplace=True)
 
medians = dict()
for title in titles:
    median = train.Age[(train["Age"!= -1& (train['Name'== title)].median()
    medians[title] = median
 
 
# In[12]:
 
 
for index, row in train.iterrows():
    if row['Age'== -1:
        train.loc[index, 'Age'= medians[row['Name']]
 
for index, row in test.iterrows():
    if row['Age'== -1:
        test.loc[index, 'Age'= medians[row['Name']]
 
train.head()
 
 
# In[13]:
 
 
medians
 
 
# In[14]:
 
 
test.isnull().sum()
 
 
# In[15]:
 
 
train.isnull().sum()
 
 
# In[16]:
 
 
test.head()
 
 
# In[17]:
 
 
test.head()
 
 
# In[18]:
 
 
test.isnull().sum()
 
 
# In[19]:
 
 
train.isnull().sum()
 
 
# In[20]:
 
 
test_age_nan_rows = test[test['Age'].isnull()]
 
 
# In[21]:
 
 
test_age_nan_rows
 
 
# In[22]:
 
 
train.head()
 
 
# ### 각 이름별로 산사람과 죽은 사람을 비교해보자.
 
# In[23]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for title in train['Name'].unique():
    fig.add_subplot(36, i)
    plt.title('Title : {}'.format(title))
    train.Survived[train['Name'== title].value_counts().plot(kind='pie')
    i += 1
 
 
# ### 각 이름별로 많이 죽은 성 -> 적게 죽은 성 순서로 값을 매기자
 
# In[24]:
 
 
title_replace = {
    'Don':0,
    'Rev':0,
    'Capt':0,
    'Jonkheer':0,
    'Mr':1,
    'Dr':2,
    'Major':3,
    'Col':3,
    'Master':4,
    'Miss':5,
    'Mrs':6,
    'Mme':7,
    'Ms':7,
    'Lady':7,
    'Sir':7,
    'Mlle':7,
    'the Countess':7
}
 
 
# In[25]:
 
 
train['Name'].unique()
 
 
# ### test에는 Dona라는 성이 있지만, train에는 없다.
 
# In[26]:
 
 
test['Name'].unique()
 
 
# In[27]:
 
 
test[test['Name'== 'Dona']
 
 
# In[28]:
 
 
train['Name'= train['Name'].apply(lambda x: title_replace.get(x))
 
 
# In[29]:
 
 
train.head()
 
 
# In[30]:
 
 
test['Name'= test['Name'].apply(lambda x: title_replace.get(x))
 
 
# In[31]:
 
 
test.isnull().sum()
 
 
# In[32]:
 
 
test[test['Name'].isnull()]
 
 
# ### Dona성을 가진 사람은 해당 성별에서 name에 대한 중간값을 넣어주자.
 
# In[33]:
 
 
test[test['Sex'== 0]['Name'].mean()
 
 
# In[34]:
 
 
train[train['Sex'== 0]['Name'].mean()
 
 
# In[35]:
 
 
test[test['Name'].isnull()]['Sex']
 
 
# In[36]:
 
 
test[test['Name'].isnull()]['Name']
 
 
# In[37]:
 
 
test['Name'= test['Name'].fillna(value=train[train['Sex'== 0]['Name'].mean())
 
 
# In[38]:
 
 
test.head()
 
 
# In[39]:
 
 
test.isnull().sum()
 
 
# In[40]:
 
 
train.isnull().sum()
 
 
# In[41]:
 
 
train_test_data = [train, test]
 
 
# ### 나이를 세분화하자, 10살부터 5살 단위로 60살까지
 
# In[42]:
 
 
for dataset in train_test_data:
    dataset.loc[ dataset['Age']<=10'Age'= 0,
    dataset.loc[(dataset['Age']>10)&(dataset['Age']<=16), 'Age'= 1,
    dataset.loc[(dataset['Age']>16)&(dataset['Age']<=20), 'Age'= 2,
    dataset.loc[(dataset['Age']>20)&(dataset['Age']<=26), 'Age'= 3,
    dataset.loc[(dataset['Age']>26)&(dataset['Age']<=30), 'Age'= 4,
    dataset.loc[(dataset['Age']>30)&(dataset['Age']<=36), 'Age'= 5,
    dataset.loc[(dataset['Age']>36)&(dataset['Age']<=40), 'Age'= 6,
    dataset.loc[(dataset['Age']>40)&(dataset['Age']<=46), 'Age'= 7,
    dataset.loc[(dataset['Age']>46)&(dataset['Age']<=50), 'Age'= 8,
    dataset.loc[(dataset['Age']>50)&(dataset['Age']<=60), 'Age'= 9,
    dataset.loc[ dataset['Age']>60'Age'= 10
 
 
# ### 나눈 나이에 대해 나이별로 죽은사람과 산사람 비율을 확인하자
 
# In[43]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for age in train['Age'].unique():
    fig.add_subplot(36, i)
    plt.title('Age : {}'.format(age))
    train.Survived[train['Age'== age].value_counts().plot(kind='pie')
    i += 1
 
 
# ### 이 또한 name과 같이 값을 매기자
 
# In[44]:
 
 
age_point_replace = {
    08,
    16,
    22,
    34,
    41,
    57,
    63,
    72,
    85,
    94,
    100
    
}
 
 
# In[45]:
 
 
for dataset in train_test_data:
    dataset['age_point'= dataset['Age'].apply(lambda x: age_point_replace.get(x))
 
 
# In[46]:
 
 
train.head()
 
 
# In[47]:
 
 
train.head()
 
 
# In[48]:
 
 
test.head()
 
 
# In[49]:
 
 
train.head()
 
 
# ### Embarked가 nan인 사람은 S로 채워주자. 이를 보다 근거있는 값으로 채울 수는 없는지 고민해보자.
 
# In[50]:
 
 
for dataset in train_test_data:
    dataset['Embarked'= dataset['Embarked'].fillna('S')
 
 
# In[51]:
 
 
embarked_mapping = {'S':0'C':1'Q':2}
for dataset in train_test_data:
    dataset['Embarked'= dataset['Embarked'].map(embarked_mapping)
 
 
# In[52]:
 
 
train.head()
 
 
# In[53]:
 
 
train.head()
 
 
# ### SibSp와 Parch값을 이용하여 FamilySize를 추가한다.
 
# In[54]:
 
 
for dataset in train_test_data:
    dataset['FamilySize'= dataset['SibSp'+ dataset['Parch'+ 1
 
 
# ### FamilySize가 4보다 큰 남자는 아버지일 확률이 높다.
# 사회적으로 아버지는 자신의 가족을 먼저 살리려고 할 것이라 생각했다.
# 여기에 나이도 추가하면 더 좋을수도 있다.
 
# In[55]:
 
 
maybe_dad_mask = (train['FamilySize'> 4& (train['Sex'== 1)
 
 
# In[56]:
 
 
maybe_dad_mask.head()
 
 
# In[57]:
 
 
train['maybe_dad'= 1
 
 
# In[58]:
 
 
train.head()
 
 
# In[59]:
 
 
train.loc[maybe_dad_mask,'maybe_dad'= 0
 
 
# In[60]:
 
 
train[train['maybe_dad'== 0].head()
 
 
# ### 그럼 아버지로 분류된 사람들이나 아버지가 아닌 사람으로 분류된 사람들의 생존비율은 어떻게 될까?
 
# In[61]:
 
 
# fig = plt.figure(figsize=(15,6))
 
# i=1
# for title in train['Name'].unique():
#     fig.add_subplot(3, 6, i)
#     plt.title('Title : {}'.format(title))
#     train.Survived[train['Name'] == title].value_counts().plot(kind='pie')
#     i += 1
fig = plt.figure()
ax1 = train.Survived[train['maybe_dad'== 1].value_counts().plot(kind='pie')
 
 
# In[62]:
 
 
ax2 = train.Survived[train['maybe_dad'== 0].value_counts().plot(kind='pie')
 
 
# In[63]:
 
 
test['maybe_dad'= 1
test_maybe_dad_mask = (test['FamilySize'> 4& (test['Sex'== 1)
test.loc[test_maybe_dad_mask,'maybe_dad'= 0
 
 
# In[64]:
 
 
test.head()
 
 
# ### FamilySize에 대해서도 새롭게 값을 매기자. 그러기 위해 FamilySize별로 생존비율 확인
 
# In[65]:
 
 
train['FamilySize'].unique()
 
 
# In[66]:
 
 
test['FamilySize'].unique()
 
 
# In[67]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for size in train['FamilySize'].unique():
    fig.add_subplot(36, i)
    plt.title('Size : {}'.format(size))
    train.Survived[train['FamilySize'== size].value_counts().plot(kind='pie')
    i += 1
 
 
# In[68]:
 
 
size_replace = {
    13,
    25,
    36,
    47,
    52,
    61,
    74,
    80,
    110
}
 
 
# In[69]:
 
 
for dataset in train_test_data:
    dataset['fs_point'= dataset['FamilySize'].apply(lambda x: size_replace.get(x))
    dataset.drop('FamilySize',axis=1,inplace=True)
 
 
# In[70]:
 
 
train.head()
 
 
# In[71]:
 
 
train.isnull().sum()
 
 
# In[72]:
 
 
test.isnull().sum()
 
 
# ### Pclass별로 생존비율 확인후 새로운 값 매기기
 
# In[73]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Pclass'].unique():
    fig.add_subplot(36, i)
    plt.title('Pclass : {}'.format(x))
    train.Survived[train['Pclass'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# In[74]:
 
 
for dataset in train_test_data:
    dataset.loc[dataset['Pclass']==3,'Pclass_point'= 0
    dataset.loc[dataset['Pclass']==2,'Pclass_point'= 1
    dataset.loc[dataset['Pclass']==1,'Pclass_point'= 2
 
 
# In[75]:
 
 
train.head()
 
 
# ### Embarked 별로
 
# In[76]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Embarked'].unique():
    fig.add_subplot(36, i)
    plt.title('Em : {}'.format(x))
    train.Survived[train['Embarked'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# In[77]:
 
 
for dataset in train_test_data:
    dataset.loc[dataset['Embarked']==0,'Em_point'= 0
    dataset.loc[dataset['Embarked']==2,'Em_point'= 1
    dataset.loc[dataset['Embarked']==1,'Em_point'= 2
 
 
# In[78]:
 
 
train.head()
 
 
# In[79]:
 
 
train.isnull().sum()
 
 
# ### Cabin은 해당인원의 숙소? 가 어디있는지에 대한 값이다. 하지만 아래와 같이 값이 너무 다양하다. 뒤의 숫자는 빼고 고려해보자
 
# In[80]:
 
 
train['Cabin'].unique()
 
 
# ### Cabin이 nan값인 사람들은 U로 채우자. U는 단지 nan값을 나타내는 문자열이다.
# ### 이를 Fare데이터와 비교해서 넣어도 좋을 것 같다. Fare의 nan값은 1개라서 일단 0으로 넣었다.
 
# In[81]:
 
 
for data in train_test_data:
    data['Cabin'].fillna('U', inplace=True)
    data['Cabin'= data['Cabin'].apply(lambda x: x[0])
    data['Cabin'].unique()
    data['Fare'].fillna(0,inplace=True)
    data['Fare'= data['Fare'].apply(lambda x: int(x))
 
 
# ### Cabin별로 생존비율 확인
 
# In[82]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Cabin'].unique():
    fig.add_subplot(36, i)
    plt.title('Cabin : {}'.format(x))
    train.Survived[train['Cabin'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# ### Fare의 값도 너무 다양하다. 왜 그러지? 이에 대해서 궁금하다.
# 일단 이를 그대로 처리하는 것은 힘들 것 같다. 이 또한 구간별로 나누어 생각해보자.
 
# In[83]:
 
 
temp = train['Fare'].unique()
temp.sort()
temp
 
 
# In[84]:
 
 
for dataset in train_test_data:
    dataset.loc[ dataset['Fare']<=30'Fare'= 0,
    dataset.loc[(dataset['Fare']>30)&(dataset['Fare']<=80), 'Fare'= 1,
    dataset.loc[(dataset['Fare']>80)&(dataset['Fare']<=100), 'Fare'= 2,
    dataset.loc[(dataset['Fare']>100), 'Fare'= 3
 
 
# ### 아까 Cabin의 값을 U로 넣어준 사람들에게 존재하는 Cabin값으로 넣어주기 위해 각 Cabin별로 어떤 Fare범위가 가장 많은지 확인하고 해당 값으로 U값을 대체한다.
 
# In[85]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Cabin'].unique():
    fig.add_subplot(36, i)
    plt.title('Cabin : {}'.format(x))
    train.Fare[train['Cabin'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# In[86]:
 
 
for dataset in train_test_data:
    dataset.loc[(dataset['Cabin'== 'U')&(dataset['Fare'== 0), 'Cabin'= 'G',
    dataset.loc[(dataset['Cabin'== 'U')&(dataset['Fare'== 1), 'Cabin'= 'T',
    dataset.loc[(dataset['Cabin'== 'U')&(dataset['Fare'== 2), 'Cabin'= 'C',
    dataset.loc[(dataset['Cabin'== 'U')&(dataset['Fare'== 3), 'Cabin'= 'B',
 
 
# In[87]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Cabin'].unique():
    fig.add_subplot(36, i)
    plt.title('Cabin : {}'.format(x))
    train.Fare[train['Cabin'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# ### Cabin의 값 별로 생존여부 확인
 
# In[88]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Cabin'].unique():
    fig.add_subplot(36, i)
    plt.title('Cabin : {}'.format(x))
    train.Survived[train['Cabin'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# In[89]:
 
 
for dataset in train_test_data:
    dataset.loc[(dataset['Cabin'== 'G'), 'Cabin_point'= 0,
    dataset.loc[(dataset['Cabin'== 'C'), 'Cabin_point'= 3,
    dataset.loc[(dataset['Cabin'== 'E'), 'Cabin_point'= 5,
    dataset.loc[(dataset['Cabin'== 'T'), 'Cabin_point'= 1,
    dataset.loc[(dataset['Cabin'== 'D'), 'Cabin_point'= 7,
    dataset.loc[(dataset['Cabin'== 'A'), 'Cabin_point'= 2,
    dataset.loc[(dataset['Cabin'== 'B'), 'Cabin_point'= 6,
    dataset.loc[(dataset['Cabin'== 'F'), 'Cabin_point'= 4,
 
 
# In[90]:
 
 
train.head()
 
 
# ### Fare별로 생존여부확인 및 점수 대체
 
# In[91]:
 
 
fig = plt.figure(figsize=(15,6))
 
i=1
for x in train['Fare'].unique():
    fig.add_subplot(36, i)
    plt.title('Fare : {}'.format(x))
    train.Survived[train['Fare'== x].value_counts().plot(kind='pie')
    i += 1
 
 
# In[92]:
 
 
for dataset in train_test_data:
    dataset.loc[(dataset['Fare'== 0), 'Fare_point'= 0,
    dataset.loc[(dataset['Fare'== 1), 'Fare_point'= 1,
    dataset.loc[(dataset['Fare'== 2), 'Fare_point'= 3,
    dataset.loc[(dataset['Fare'== 3), 'Fare_point'= 2,
 
 
# In[93]:
 
 
# for dataset in train_test_data:
#     dataset['parent'] = 1
#     dataset.loc[(dataset['Parch'] > 0) & (dataset['Age'] >= 4), 'parent'] = 0
 
 
# In[94]:
 
 
# train.Survived[train['parent'] == 1].value_counts().plot(kind='pie')
 
 
# In[95]:
 
 
# train.Survived[train['parent'] == 0].value_counts().plot(kind='pie')
 
 
# ### 모든 값을 정규화? 한다. 정규화랑 좀 다른 것일지도 모른다. 해당 내용에 대해서는 한번 더 공부가 필요하다.
# 단지 이것을 하지 않았을 때 보다 했을 때 결과가 더 좋았다.. 왜일까?
 
# In[96]:
 
 
from sklearn.preprocessing import StandardScaler
for dataset in train_test_data:
    dataset['Name'= StandardScaler().fit_transform(dataset['Name'].values.reshape(-11))
    dataset['Sex'= StandardScaler().fit_transform(dataset['Sex'].values.reshape(-11))
    dataset['maybe_dad'= StandardScaler().fit_transform(dataset['maybe_dad'].values.reshape(-11))
    dataset['fs_point'= StandardScaler().fit_transform(dataset['fs_point'].values.reshape(-11))
    dataset['Em_point'= StandardScaler().fit_transform(dataset['Em_point'].values.reshape(-11))
    dataset['Cabin_point'= StandardScaler().fit_transform(dataset['Cabin_point'].values.reshape(-11))
    dataset['Pclass_point'= StandardScaler().fit_transform(dataset['Pclass_point'].values.reshape(-11))
    dataset['age_point'= StandardScaler().fit_transform(dataset['age_point'].values.reshape(-11))
    dataset['Fare_point'= StandardScaler().fit_transform(dataset['Fare_point'].values.reshape(-11))
 
 
# ### 필요없는 속성 지우기
 
# In[97]:
 
 
train.drop(['PassengerId','Pclass','SibSp','Parch','Ticket','Fare','Embarked','Cabin','Age'], axis=1, inplace=True)
test.drop(['Pclass','SibSp','Parch','Ticket','Fare','Embarked','Cabin','Age'], axis=1, inplace=True)
 
 
# In[98]:
 
 
train.head()
 
 
# In[99]:
 
 
train_data = train.drop('Survived', axis=1)
target = train['Survived']
 
 
# In[100]:
 
 
train_data.head()
 
 
# In[101]:
 
 
target.head()
 
 
# In[102]:
 
 
test.shape
 
 
# In[103]:
 
 
train.shape
 
 
# In[104]:
 
 
train_data.shape
 
 
# ### SVC를 이용하여 결과를 만들었다.
 
# In[105]:
 
 
 
# Importing Classifier Modules# Import 
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
 
import numpy as np
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
k_fold = KFold(n_splits=10, shuffle=True, random_state=0)
clf = SVC()
# clf = DecisionTreeClassifier()
clf.fit(train_data, target)
 
test_data = test.drop("PassengerId", axis=1).copy()
prediction = clf.predict(test_data)
submission = pd.DataFrame({
        "PassengerId": test["PassengerId"],
        "Survived": prediction
    })
 
submission.to_csv('submission_test1.csv', index=False)
submission = pd.read_csv('submission_test1.csv')
submission.head()
 
 
cs


jupyter notebook에서 작성한 코드를 python 코드로 그대로 가져와 가독성이 매우 떨어질 수 있습니다.

아래의 github에서는 보다 보기 좋게 확인하실 수 있습니다.


https://github.com/doorBW/kaggle_practice/blob/master/titanic/80pcts_solution_180603/Beomwoo_Titanic_solution.ipynb

'Kaggle' 카테고리의 다른 글

Kaggle 타이타닉(Titanic) 80.3% 성공 후기 및 코드  (0) 2018.06.04
블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc