본문 바로가기
AI/데이터 사이언스

[AI 부트캠프] DAY 21 - 파이썬 EDA 1

by HOHHOH 2023. 8. 15.

[오늘의 일지]

파이썬 EDA 실시간 강의 - Numpy, Pandas

[상세 내용]

파이썬 EDA

EDA

- 정의 : 우선 수업을 듣기에 앞서서 EDA란 단어를 몰라서 찾아봤습니다. EDA는 Exploratory Data Analysis의 약어로 탐색적 데이터 분석이라는 뜻을 가지고 있습니다. 처음 시작은 벨연구소의 수학자 존 튜키가 개발한 데이터분석 방법론으로, 데이터를 다양한 각도에서 관찰하고 이해하는 모든 과정을 말한다고 합니다. 

 

Numpy

- Numpy는 Numerical computing with Python의 약어로서 수치연산 및 벡터 연산에 최적화된 파이썬 라이브러리를 의미한다고 합니다. Numpy는 2005년에 만들어졌으며 100%로 오픈소스입니다.

- Numpy의 주요 특징은 파이썬이 가지고 있는 취약한 수치 연산 부분에서 안정성을 보장합니다. 그렇기 때문에 N차원 실수값 연산에 최적화되어 있다고 합니다. 이 말은 N개의 실수로 이루어진 벡터 연산에 최적화되어 있다는 말과 같은 말입니다.

- Numpy는 사용 시 numpy array 구조로 사용이 됩니다. 이 구조는 파이썬에서 사용하는 리스트의 구조와 비슷한 구조를 가지고 있지만 세부적인 특징에서는 C언어의 array 구조와 동일한 개념이라 합니다. 아래는 numpy array의 1차원, 2차원 , 3차원 구조를 그림으로 알기 쉽게 표현해 놓은 것입니다.

출처:https://towardsdatascience.com/numpy-array-cookbook-generating-and-manipulating-arrays-in-python-2195c3988b09

 

- Numpy의 데이터 구조는 일반 파이썬과 다른 구조를 가지고 있다.

출처:https://lifewithdata.com/2022/04/02/numpy-array-data-types-with-examples/

 

- Numpy 기초 연습

# numpy 라이브러리를 불러옵니다.
import numpy as np

# 파이썬 리스트 선언
data =  [1, 2, 3, 4]

# 파이썬 2차원 리스트(행렬) 선언
data2 = [[1, 2],
        [3, 4]]
        
# 파이썬 list를 numpy array로 변환합니다.

# numpy array를 만드는 방식의 대부분은 파이썬 리스트를 np.array로 변환하는 방식입니다.
arr = np.array(data)
arr
>>>
array([1, 2, 3, 4])

# 2차원 리스트를 np.array로 만듭니다.
arr2 = np.array(data2) # data2라는 리스트를 numpy array로 만들어라.
arr2
>>>
array([[1, 2],
       [3, 4]])

 

- 숫자를 자동으로 생성하는 array

# 0부터 9까지 숫자를 자동으로 생성한 array
# np.arange(0, 10)
# np.zeros(5)
# np.ones(7)
# np.empty(5)  # uninitialized
np.linspace(1, 50, 50) # 0부터 50까지의 범위에서 50개의 등분을 찾아주는 함수

 

- Numpy array 연산

# v1 = (1, 2, 3), v2 = (4, 5, 6) 벡터 2개 생성하기.
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])

#  vector addition
v1 + v2
>>>
array([5, 7, 9])

#  vector subtraction
v1 - v2
>>>
array([-3, -3, -3])

# (not vector operation) elementwise multiplication
v1 * v2
>>>
array([ 4, 10, 18])

# (not vector operation) elementwise division
v1/v2
>>>
array([0.25, 0.4 , 0.5 ])

# dot product (내적)
v1 @ v2
>>>
32

 

- Numpy의 Broadcast : 크기가 다른(차원이 다른) numpy array를 연산할 때, 자동으로 연산을 전파(broadcast)해주는 기능. 행렬곱 연산을 할 때 편리하다.

arr1 = np.array([1, 0, 0]) # 1d array 
arr3 = np.array([[1], [0], [0]]) # 2d array
arr2 = np.array([[1, 2, 3],
                 [4, 5, 6]]) # 2d array
 
 # Shape은 array의 구조를 알려주는 함수이다
print(arr1.shape)
print(arr2.shape)
print(arr3.shape)
>>>
(3,)
(2, 3)
(3, 1)

# 2개의 array를 더해보면? [arr1 + arr2[0], arr 1 + arr2[1]]의 형태로 자동으로 더해준다
arr1 + arr2
>>>
array([[2, 2, 3],
       [5, 5, 6]])

# 2개의 array를 곱해보면?
arr1 * arr2
>>>
array([[1, 0, 0],
       [4, 0, 0]])

 

- Universal Function : broadcast 기능의 확장으로서 numpy array의 모든 원소에 동일한 함수를 반복문으로 적용한 것과 같은 효과를 내는 기능입니다.

arr = np.array([1., 2., 3., 4.])

f = lambda x : 1/x
for i in range(len(arr)):
    arr[i] = f(arr[i])    
print(arr)
# numpy에서는 그냥 이렇게 표현이 가능하다
1/arr

 

- Fancy Indexing : Numpy array는 list의 indexing을 확장하여 다양한 조건에서의 indexing을 지원한다.

arr1 = np.arange(10)
arr1
>>>
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 첫번째 원소
arr1[0]
>>>0

# 마지막 원소
arr1[-1]
>>>9

# 앞에서부터 원소 3개 slicing
arr1[:3]
>>>
array([0, 1, 2])

arr2 = np.array([[1, 2, 3, 4],
               [5, 6, 7, 8],
               [9, 10, 11, 12]])
arr2

# arr2.shape >>> (3, 4)
## np.array.shape의 규칙 : 괄호 앞에서부터 제일 바같 []의 원소의 개수부터 안쪽 []까지 차례대로 적는다.

# arr2의 2row, 3column 원소 = 7
arr2[1][2]
arr2[1, 2]
>>>7

# arr2의 세번째 column [3, 7, 11]
arr2[:, 2]
>>>
array([ 3,  7, 11])

# arr2의 두번째 row
arr2[1, :]
>>>
array([5, 6, 7, 8])

# arr2에서 두번째 row중에서 6보다 큰 원소들 찾기
mask = arr2[1, :] >6 # filter : True 위치에 있는 데이터만 출력
arr2[1, :][mask] # mask를 indexing에 사용하려면, mask 조건에 해당하는 원소만 출력됨.
>>>
array([7, 8])

# arr2의 두번째 column중에서 6보다 큰 원소들 찾기
# arr2p[row에 대한 조건, col에 대한 조건]
arr2[arr2[:, 1]> 6, 1]
# [DEBUG] mask의 크기가 내가 적용할 대상의 크기와 동일한지 확인.
>>>
array([10])

arr2[arr2[:, 0]> 8 # 첫번째 column에서 8보다 큰 원소가 있는 row를 출력하세요(이 조건에 하나라도 만족하지 못하면 출력안한다.) , 
arr2[[False, False, True]] 3번째 행을 출력
arr2[2] # True인 원소만 출력
>>>
array([[ 9, 10, 11, 12]]) # 위에 세개 다 같은 값

 

Pandas

- 판다스(Pandas)는 파이썬 데이터 처리를 위한 라이브러리입니다. 파이썬을 이용한 데이터 분석과 같은 작업에서 필수 라이브러리로 알려져 있습니다. 판다스를 사용하면 자신이 사용하는 데이터 자료를 보기도 깔끔하고 관리하기도 쉽게 이용할 수 있다고 합니다. 그리고 수업시간에 주의를 준 것이 있는데 판다스 버전은 1.5.3 이하로 사용하라고 말했습니다. 2.0 이상의 버전부터는 바뀐 부분이 있어서 적용이 안 되는 부분이 많다고 했습니다.

 

- Pandas 기초 연습

import pandas as pd
# pandas 라이브러리를 불러옵니다. pd를 약칭으로 사용합니다.
pd.Series([1, 3, 5, 6, 8]) # index, values(data), dtype
>>>
0    1
1    3
2    5
3    6
4    8
dtype: int64
# 12x4 행렬에 1부터 48까지의 숫자를 원소를 가지고, 
# index는 2023-08-01부터 시작하고, coulmns은 순서대로 X1, X2, X3, X4로 하는 DataFrame 생성
df = pd.DataFrame(data=np.arange(1, 49).reshape(12, 4), # (48, ) -> (12, 4)
                 index=pd.date_range(start='20230801', end='20230812' , freq = 'D'),
                 columns=["X1", "X2", "X3", "X4"])
df
>>>

주피터 노트북을  통해 보면 더 깔끔하게 나온다

# dataframe columns
df.columns
>>>
Index(['X1', 'X2', 'X3', 'X4'], dtype='object')

# dataframe values
df.values
>>>
array([[ 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]])
       
# 특정 column을 가져오기
df["X1"]
# df['2023-08-01'] # not column name
>>>
2023-08-01     1
2023-08-02     5
2023-08-03     9
2023-08-04    13
2023-08-05    17
2023-08-06    21
2023-08-07    25
2023-08-08    29
2023-08-09    33
2023-08-10    37
2023-08-11    41
2023-08-12    45
Freq: D, Name: X1, dtype: int32

# X1 column에 2 더하기 (universal function 지원)
df['X1'] + 2
>>>
2023-08-01     3
2023-08-02     7
2023-08-03    11
2023-08-04    15
2023-08-05    19
2023-08-06    23
2023-08-07    27
2023-08-08    31
2023-08-09    35
2023-08-10    39
2023-08-11    43
2023-08-12    47
Freq: D, Name: X1, dtype: int32

 

- Dataframe 기초 method

# dataframe의 맨 위 다섯줄을 보여주는 head()
df.head() # 디폴트값이 5줄인데 ()안에 원하는 숫자를 쓰면 원하는 숫자만큼 나온다
>>>
        	X1	X2	X3	X4
2023-08-01	1	2	3	4
2023-08-02	5	6	7	8
2023-08-03	9	10	11	12
2023-08-04	13	14	15	16
2023-08-05	17	18	19	20

# 반대 개념으로는 df.tail() 있다
df.tail()
>>>

       		X1	X2	X3	X4
2023-08-08	29	30	31	32
2023-08-09	33	34	35	36
2023-08-10	37	38	39	40
2023-08-11	41	42	43	44
2023-08-12	45	46	47	48

# dataframe에 대한 전체적인 요약정보를 보여줍니다. index, columns, null/not-null/dtype/memory usage가 표시됩니다.
df.info()
>>>
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 12 entries, 2023-08-01 to 2023-08-12
Freq: D
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   X1      12 non-null     int32
 1   X2      12 non-null     int32
 2   X3      12 non-null     int32
 3   X4      12 non-null     int32
dtypes: int32(4)
memory usage: 288.0 bytes

# dataframe에 대한 전체적인 통계정보를 보여줍니다.
df.describe()
>>>
			X1	       X2	       X3	       X4
count		12.000000	12.000000	12.000000	12.000000
mean		23.000000	24.000000	25.000000	26.000000
std		14.422205	14.422205	14.422205	14.422205
min		1.000000	2.000000	3.000000	4.000000
25%		12.000000	13.000000	14.000000	15.000000
50%		23.000000	24.000000	25.000000	26.000000
75%		34.000000	35.000000	36.000000	37.000000
max		45.000000	46.000000	47.000000	48.000000

# X2 column를 기준으로 (데이터를) 내림차순 정렬 ## sort with expansion
df.sort_values(by="X2", ascending=False)
>>>	
                X1	X2	X3	X4
2023-08-12	45	46	47	48
2023-08-11	41	42	43	44
2023-08-10	37	38	39	40
2023-08-09	33	34	35	36
2023-08-08	29	30	31	32
2023-08-07	25	26	27	28
2023-08-06	21	22	23	24
2023-08-05	17	18	19	20
2023-08-04	13	14	15	16
2023-08-03	9	10	11	12
2023-08-02	5	6	7	8
2023-08-01	1	2	3	4

 

- Fancy Indexing :

# pandas dataframe은 column 이름을 이용하여 기본적인 Indexing이 가능합니다.
# X1 column을 indexing
df['X3']
df.X2 # column name
>>>
2023-08-01     2
2023-08-02     6
2023-08-03    10
2023-08-04    14
2023-08-05    18
2023-08-06    22
2023-08-07    26
2023-08-08    30
2023-08-09    34
2023-08-10    38
2023-08-11    42
2023-08-12    46
Freq: D, Name: X2, dtype: int32

# dataframe에서 slicing을 이용하면 row 단위로 잘려나옵니다.
# 앞에서 3줄을 slicing 합니다.
df[:3]
>>>
		X1	X2	X3	X4
2023-08-01	1	2	3	4
2023-08-02	5	6	7	8
2023-08-03	9	10	11	12

# df.loc는 특정값을 기준으로 indexing합니다. (key - value)
## df.loc[row에 대한 조건, col에 대한 조건]
df.loc['20230801']
>>>
X1    1
X2    2
X3    3
X4    4
Name: 2023-08-01 00:00:00, dtype: int32

# df.loc에 2차원 indexing도 가능합니다.
# df.loc[index, columns]
df.loc['20230807', 'X3'] # 특정 원소 하나 뽑기
df.loc[['20230801','20230805'],['X1','X4']] # 불연속적인 row, col 뽑기
df.loc['20230803':'20230810', 'X2':"X4"] # 연속적인 row, col 뽑기

# dataframe에 조건식을 적용해주면 조건에 만족하는지 여부를 알려주는 "mask"가 생깁니다.
# Q. df에서 X3 column에 있는 원소들중에 3의 배수만 출력해주세요!
df.X3 % 3 == 0 # boolean mask
df.loc[df.X3 % 3 == 0, 'X3' ]

# Q. df에서 X2 column에 있는 원소들 중에 20 보다 큰 원소들을 출력해주세요
df.loc[df.X2 > 20, 'X2']
>>>
2023-08-06    22
2023-08-07    26
2023-08-08    30
2023-08-09    34
2023-08-10    38
2023-08-11    42
2023-08-12    46
Freq: D, Name: X2, dtype: int32

# 2차원 리스트 indexing과 같은 원리가 되었습니다.
# integer-location based indexing ## iloc
df.iloc[2, 3]
>>>12

# iloc로 2차원 indexing을 하게되면, row 기준으로 index 3,4를 가져오고 column 기준으로 0, 1을 가져옵니다.
df.iloc[[3,4],[0,1]]
df.iloc[5:8,1:3]
# df.iloc[df.X2 > 20, 1] ## boolean mask로 indexing이 안됨.
>>>
# iloc로 2차원 indexing을 하게되면, row 기준으로 index 3,4를 가져오고 column 기준으로 0, 1을 가져옵니다.
df.iloc[[3,4],[0,1]]
df.iloc[5:8,1:3]
# df.iloc[df.X2 > 20, 1] ## boolean mask로 indexing이 안됨.
1
# iloc로 2차원 indexing을 하게되면, row 기준으로 index 3,4를 가져오고 column 기준으로 0, 1을 가져옵니다.
2
df.iloc[[3,4],[0,1]]
3
df.iloc[5:8,1:3]
4
# df.iloc[df.X2 > 20, 1] ## boolean mask로 indexing이 안됨.
       		X2	X3
2023-08-06	22	23
2023-08-07	26	27
2023-08-08	30	31

 

[마무리]

 이번주차부터는 진짜로 데이터를 다루는 라이브러리인 Numpy와 Pandas에 대한 수업이 시작되었습니다. 부트캠프를 시작한 지 약 한 달 만에 데이터를 다룰 수 있는 파트까지 온 것인데요. 이제부터는 진짜 관심이 있던 분야에 대해서 시작하는 것이기 때문에 점점 흥미가 증가하는 것 같습니다. 

반응형

댓글