Basic Data Structures

NumPy with ndarray

강의 홍보

Numpy ndarray 개요

  • 넘파이 array()는 ndarray로 변환 가능
  • 생성된 ndarray배열의 shape변수는 ndarray의 크기, 행과 열의 수를 튜플 형태로 가지고 있으며, 이를 통해 ndarray 배열의 차원까지 알 수 있음

(1) 배열이란?

  • NumPy에서 배열은 동일한 타입의 값을 가짐
  • shape는 각 차원의 크기를 튜플로 표시한다.
  • 차원이란 무엇일까?
    • 1차원은 보통 하나의 을 의미
    • 2차원은 평면을 의미하고, 데이터 분석에서는 보통 데이터프레임을 의미한다.
    • 3차원은 공간을 의미하고, 딥러닝에서는 보통 이미지를 의미한다. (RGB)

shape와 ndim

  • 코드를 통해서 shapendim 함수를 확인해본다.

(1) 함수 활용 예제

  • 우선 소스코드를 통해 1차원, 2차원, 3차원 함수를 만들어 봅니다.
import numpy as np
array1 = np.array([1,2,3,4,5])
print('array1 type:',type(array1))
print('array1 array 형태:',array1.shape)

array2 = np.array([[1,2,3,4,5],
                  [2,3,4,5,6]])
print('array2 type:',type(array2))
print('array2 array 형태:',array2.shape)

array3 = np.array([[[1,2,3,4,5,6]], [[3,4,5,6,7,8]]])
print('array3 type:',type(array3))
print('array3 array 형태:',array3.shape)
array1 type: <class 'numpy.ndarray'>
array1 array 형태: (5,)
array2 type: <class 'numpy.ndarray'>
array2 array 형태: (2, 5)
array3 type: <class 'numpy.ndarray'>
array3 array 형태: (2, 1, 6)

(2) shape

  • 1차원의 shape는 (3, )인데, 이는 array로 5개의 데이터를 가지고 있다는 뜻임
  • 2차원의 shape는 (2, 5)이며, 이는 array로 2차원 데이터로 2 x 5 = 10, 즉 총 10개의 데이터가 있음
  • 3차원의 shape는 (2, 1, 6)이며, 이는 array로 3차원 데이터로 2 x 1 x 6 = 12, 즉 총 12개의 데이터가 있음
  • 차원을 직관적으로 확인하려면 ndim 메서드를 사용하면 된다.
print('array1: {:0}차원, array2: {:1}차원, array3: {:2}차원'.format(array1.ndim, array2.ndim, array3.ndim))
array1: 1차원, array2: 2차원, array3:  3차원

데이터 타입

  • ndarray내 데이터값은 숫자 값, 문자열 값, 불 값 모두 가능
  • 숫자형의 경우 int형, float형 등이 제공됨
    • int: 8, 16, 32
    • float: 16, 32, 64, 128
  • 간단한 예제로 확인한다.
num_list = [7, 8, 9, 10]
print(type(num_list))
num_array = np.array(num_list)
print(type(num_array))
print(num_array, num_array.dtype)
<class 'list'>
<class 'numpy.ndarray'>
[ 7  8  9 10] int64

reshape의 중요성

  • shape를 통해 데이터를 이해하는 것은 매우 중요하다.
  • 머신러닝 알고리즘 또는 선형대수를 잘 모른다 할지라도, 머신러닝 및 데이터 세트 간의 입출력과 변환 수행 시, 1차원 데이터 또는 다차원 데이터를 요구하는 경우가 있다.
    • 이 때, 차원이 달라서 오류가 발생할 가능성이 크니, 주의를 해야 한다.
  • 이 때, 차원을 맞추는 방법으로 reshape()를 활용한다.

(1) 소스 예제

  • 다음 예제는 0~14까지의 1차원 ndarray2x5형태로, 그리고 5x2 2차원 ndarray로 변환한다.
array1 = np.arange(15)
print('array1:\n', array1)

array2 = array1.reshape(3,5)
print('array2:\n',array2)

array3 = array1.reshape(5,3)
print('array3:\n',array3)
array1:
 [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]
array2:
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
array3:
 [[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]]
array1.reshape(4,3)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-8-a40469ec5825> in <module>()
----> 1 array1.reshape(4,3)


ValueError: cannot reshape array of size 15 into shape (4,3)
  • 위 에러는 변경이 불가능한데, 당연한 얘기이지만, size가 맞지 않다.

(2) -1의 활용

  • 실전에서는 주로 -1을 활용한다.
  • -1을 인자로 사용하면 원래 ndarray와 호환되는 새로운 shape로 변환해준다.
  • 예제를 통해서 살펴보도록 한다.
array_1 = np.arange(15)
print(array_1)

array_2 = array_1.reshape(-1,5)
print('array2 shape:',array_2.shape)

array_3 = array_1.reshape(5,-1)
print('array3 shape:',array_3.shape)
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]
array2 shape: (3, 5)
array3 shape: (5, 3)
  • array_1은 1차원 ndarray로 0~14까지의 데이터를 가지고 있다.
  • array_2array_1과 호환될 수 있는 2차원 ndarray로 변환되고, 고정된 5개의 칼럼에 맞는 로우를 자동으로 새롭게 생성해 변환하는 의미를 가진다.
    • array_3도 반대로 적용할 수 있다.
  • 그런데, 호환될 수 없는 형태는 에러가 날 것이다.

(3) 차원변환

  • 3차원을 2차원으로, 1차원을 2차원으로 변경하는 코드를 작성할 수 있다.
  • 이 때, reshape(a1, a2, a3)에서, b = a1 x a2 x a3의 값이 arrange(b)이 된다.
array_1 = np.arange(27)
array_3d = array_1.reshape((3,3,3))
print('array3d:\n',array_3d.tolist())

# 3차원 ndarray를 2차원 ndarray로 변환
array_5 = array_3d.reshape(-1,1)
print('array5:\n',array_5.tolist())
print('array5 shape:',array_5.shape)

# 1차원 ndarray를 2차원 ndarray로 변환
array_6 = array_1.reshape(-1,1)
print('array6:\n',array_6.tolist())
print('array6 shape:',array_6.shape)
array3d:
 [[[0, 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]]]
array5:
 [[0], [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]]
array5 shape: (27, 1)
array6:
 [[0], [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]]
array6 shape: (27, 1)

선형대수 연산

  • 행렬 내적은 행렬 곱이며, np.dot()을 활용한다.

How to create my own function

강의 홍보

I. 개요

  • 나만의 함수를 작성해 본다.
  • 실행가능한 함수를 만들어 본다.

II. 기존 내장 함수

  • 함수는 특정 기능을 수행하는 코드를 의미한다.
  • 함수는 Sum(), Len()을 의미한다.
x = [1,2,3,4,5]
print(sum(x))
print(len(x))
5

III 사용자 정의 함수 예제

  • 이제 사용자 정의 함수를 사용하자.
  • 함수 선언 시, defdefine의 약자다.
def my_avg(x):
  sum_var = sum(x)
  len_var = len(x)
  return sum_var / len_var

print(my_avg(x))
3.0
  • 기본적인 사용정의 함수는 크게 매개 변수return으로 이루어진다.
    • 이 때의 매개변수는, string, int, DataFrame 등 다양하게 올 수 있다.
    • return의 의미는 일종의 함수를 실행한 뒤 반환하려는 output이다.

IV. 파이썬에서 실행모드 구축하기

  • 사용자 정의 함수를 작성하였다면, 이제부터는 Main() 함수를 활용하여 코드를 빠르게 실행할 수 있도록 한다. 아래와 같이 코드를 작성하자.
  • PyCharm, VSCode에서 main.py 안에 아래와 같이 코드를 작성해본다.
# -*- coding: utf-8 -*-

def main():
  print("안녕하세요, Main() 입니다. ")

if __name__ == "__main__":
  main()
안녕하세요, Main() 입니다. 
  • 위 구문은 일종의 파이썬 파일을 실행시키기 위한 일종의 규약이라 이해하면 좋을 것 같다.
  • __name__은 모듈의 이름이 저장되는 곳이다.
  • __main__은 모듈의 시작점과 같다. main.py에서 __name__=="__main__"은 바꾸지 않는다.
  • 이 때, 위 파일을 작성하면, shell에서 다음과 같이 실행한다.
~ $ python main.py
안녕하세요, Main() 입니다. 

(1) 파일 구조

  • 크게 두개의 파일을 작성할 것이다.
    • calculation.py
    • main.py
  • calculation.py에서 기본적인 코드를 작성한 뒤, main.py에서 해당 모듈을 가져와서 함수를 사용할 것이다.

(2) calculation.py 파일 작성 및 실행

  • 간단하게 사직연산 함수를 작성한다.
# -*- coding: utf-8 -*-
a = 3
b = 4

def plus(a, b): 
  c= a+b
  return c

def subtract(a, b):
  c = a-b
  return c

if __name__ == "__main__":
  print("a + b =", subtract(a, b))
  print("a - b =", plus(a, b))
  • 위와 같이 파일을 작성한 뒤 저장한다.
  • 그리고, shell에서 다음과 같이 실행한다.
~ $ python calculation.py
a + b = -1
a - b = 7

(3) main.py 작성 및 실행

  • 기존 calculation.py에서 if~이하의 구문을 제거한 후, 다시 저장한다.
  • 이번에는 main.py에서 아래와 같이 파일을 작성한다.
# -*- coding: utf-8 -*-
import calculation as cal

a = 3
b = 4

def main():
  print("안녕하세요, Main() 입니다. ")
  print("a + b =", cal.subtract(a, b))
  print("a - b =", cal.plus(a, b))

if __name__ == "__main__":
  main()
  • 그리고 이번에는 shell에서 main.py를 실행한다.
~ $ python main.py
안녕하세요, Main() 입니다. 
a + b = -1
a - b = 7

(4) 소결론

  • 같은 파일 경로에 있다면, 다른 file에서 함수(=module)을 불러올 때는 패키지에서 파일을 불러오는 것처럼, import ~형태로 사용할 수 있다.
  • 그리고, 각 파일명 안에는 다양한 작성할 수 있고, 또한 불러올 수 있다.

V. 두개의 폴더를 활용한 실행모드 구축

  • 이제 한 폴더 안에서 다른 파일의 함수를 불러올 수 있음을 확인하였다.
  • 이제는 두개의 폴더를 만들어 각각의 기능을 구현해본다.
  • 폴더는 크게 두가지다.
    • 사칙연산을 의미하는 arithmetic
    • 데이터 전처리를 의미하는 dataPreprocessing
  • 각각의 폴더안에 각 2가지의 파일을 작성할 예정이다.
  • 마지막으로 main.py는 독립적으로 위치해 놓는다.

(1) Arithmetic 폴더

  • plus.pysubtract.py안에 함수를 각각 저장한 뒤 작성한다.
    • plus.py
# -*- coding: utf-8 -*-
def add(a, b): 
  c= a+b
  return c
  • subtract.py
# -*- coding: utf-8 -*-
def minus(a, b):
  c = a-b
  return c

(2) dataPreprocessing 폴더

  • 파일 불러오기를 실행하는 importData.py와 데이터 전처리를 담당하는 processing.py에 해당하는 소스코드 작성 후 각각 저장한다.
    • importData.py
# -*- coding: utf-8 -*-

def readData():
    print("~~ 데이터를 불러옵니다 ~~ ")
    data = "빅쿼리에서 불러오는 데이터"
    return data
  • processing.py
# -*- coding: utf-8 -*-
from time import sleep

def process_data(data):
    print("~~ 데이터 전처리 함수를 실행합니다! ~~")
    modified_data = data + "가 수정 완료 되었습니다."
    sleep(3)
    print("~~ 데이터 전처리가 끝났습니다! ~~")
    return modified_data

(3) main.py 수정

  • 다음은 main.py를 아래와 같이 수정하도록 한다.
# -*- coding: utf-8 -*-
from arithmetic import plus as pl
from arithmetic import subtract as sub
from dataPreprocessing import processing
from dataPreprocessing import importData

a = 3
b = 4

def main():
  print("~~ 사칙 연산을 시작합니다 ~~ ")
  print("a + b =", sub.minus(a, b))
  print("a - b =", pl.add(a, b))
  print("~~ 사칙 연산을 종료합니다 ~~ ")

  ## 데이터 전처리 시작
  data = importData.readData()
  processing.process_data(data)

if __name__ == "__main__":
  main()
  • 그 다음 shell에서 다음과 같이 실행하면 아래와 같은 결과물을 얻게 될 것이다.
~ $ python main.py
~~ 사칙 연산을 시작합니다 ~~ 
a + b = -1
a - b = 7
~~ 사칙 연산을 종료합니다 ~~ 
~~ 데이터를 불러옵니다 ~~ 
~~ 데이터 전처리 함수를 실행합니다! ~~
~~ 데이터 전처리가 끝났습니다! ~~

(4) 파일구조 리뷰

  • 파일 구조는 아래와 같다.
.
├── arithmetic # 폴더
│   ├── plus.py
│   └── subtract.py
├── dataPreprocessing # 폴더
│   ├── importData.py
│   └── processing.py
├── main.py

VI. 결론

  • from의 각각의 폴더명을 의미한다.
  • import는 동일 폴더내의 다양한 py 파일명을 의미한다.
  • 각각의 파일명안에 있는 다양한 함수들을 불러와서 사용할 수 있다.
  • 프로젝트 파일을 제출할 시에는 위와 같이 main.py를 실행만 하더라도 결과가 나올 수 있도록 프로젝트 파일을 Refactoring해서 업로드하는 것을 추천한다.

머신러닝 데이터 전처리 1 - 결측치 처리

개요

I. 구글 드라이브 연동

  • 구글 코랩을 시작하면 언제든지 가장 먼저 해야 하는 것은 드라이브 연동이다.
from google.colab import drive # 패키지 불러오기 
from os.path import join  

ROOT = "/content/drive"     # 드라이브 기본 경로
print(ROOT)                 # print content of ROOT (Optional)
drive.mount(ROOT)           # 드라이브 기본 경로 Mount

MY_GOOGLE_DRIVE_PATH = 'My Drive/Colab Notebooks/inflearn_kaggle/' # 프로젝트 경로
PROJECT_PATH = join(ROOT, MY_GOOGLE_DRIVE_PATH) # 프로젝트 경로
print(PROJECT_PATH)
/content/drive
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
/content/drive/My Drive/Colab Notebooks/inflearn_kaggle/
%cd "{PROJECT_PATH}"
/content/drive/My Drive/Colab Notebooks/inflearn_kaggle
!ls
data  docs  source
  • 필자는 inflearn_kaggle 폴더안에 data, docs, source 등의 하위 폴더를 추가로 만들었다.
  • 즉, data 안에 다운로드 받은 파일이 있을 것이다.

II. 프로젝트 관련 패키지 불러오기

  • 데이터 과학 관련 패키지들을 불러온다.
import pandas as pd
import pandas_profiling
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
import seaborn as sns

from IPython.core.display import display, HTML
  • 시각화 진행 시, 일정한 Template을 작성한다.
%matplotlib inline
import matplotlib.pylab as plt

plt.rcParams["figure.figsize"] = (14,4)
plt.rcParams['lines.linewidth'] = 2
plt.rcParams['lines.color'] = 'r'
plt.rcParams['axes.grid'] = True 

III. 데이터 불러오기

  • train.csvtest.csv 데이터를 불러와서 확인해보는 소스코드를 작성한다.
train = pd.read_csv('data/train.csv')
test = pd.read_csv('data/test.csv')
print("data import is done")
data import is done
  • 실제로 데이터가 잘 불러와졌는지 다시한번 확인해본다.
train.shape, test.shape
((1460, 81), (1459, 80))
  • 이제 데이터 전처리를 위한 사적 작업이 모두 종료된 것이다.

IV. 결측치 처리방법 1 - “None” 또는 0으로 채우기

  • 결측치 처리방법은 크게 2가지가 있다.
    • 데이터 삭제 또는 데이터 채우기
  • 데이터 삭제 진행하는 코드는 아래 튜토리얼을 확인한다.
  • 본 포스트에서는 데이터를 채우는 방법에 대해 소개한다.

(1) 전체 데이터 결측치 확인

  • 전체 데이터 결측치를 확인하는 방법은 아래와 같다.
new_df = train.copy()

new_df_na = (new_df.isnull().sum() / len(new_df)) * 100
new_df_na.sort_values(ascending=False).reset_index(drop=True)
new_df_na = new_df_na.drop(new_df_na[new_df_na == 0].index).sort_values(ascending=False)[:30]
new_df_na
PoolQC          99.520548
MiscFeature     96.301370
Alley           93.767123
Fence           80.753425
FireplaceQu     47.260274
LotFrontage     17.739726
GarageYrBlt      5.547945
GarageType       5.547945
GarageFinish     5.547945
GarageQual       5.547945
GarageCond       5.547945
BsmtFinType2     2.602740
BsmtExposure     2.602740
BsmtFinType1     2.534247
BsmtCond         2.534247
BsmtQual         2.534247
MasVnrArea       0.547945
MasVnrType       0.547945
Electrical       0.068493
dtype: float64
  • 위 데이터를 가지고 시각화를 진행한다.
f, ax = plt.subplots(figsize=(15, 12))
plt.xticks(rotation='90')
sns.barplot(x=new_df_na.index, y=new_df_na)
plt.xlabel('Variables', fontsize=24)
plt.ylabel('Percent of missing values', fontsize=24)
plt.title('Percent missing data by Variable', fontsize=32)
plt.show()

png

Python for loop example

강의 홍보

I. 개요

  • 지난 시간에 for_loop의 기본적인 개념에 대해 살펴봤다.
  • 이번 시간에는 for_loop의 실제 다양한 활용 방안에 대해 살펴본다.

II. 데이터 시각화

  • 변수의 개수에 상관없이 for-loop를 활용하면 무한대로 시각화를 작성할 수 있다.
  • 빠르게 코드로 확인해본다.
  • IRIS 데이터를 수집하는 코드를 작성한다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets

iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
print(df.head())
   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
0                5.1               3.5                1.4               0.2
1                4.9               3.0                1.4               0.2
2                4.7               3.2                1.3               0.2
3                4.6               3.1                1.5               0.2
4                5.0               3.6                1.4               0.2
  • 변수별로 시각화를 작성하기 위해, 우선 변수명을 List에 포함한다.
feature_names = iris.feature_names
print(feature_names)
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
  • 다음 코드는 시각화 작성을 위한 기본 환경설정이다.
  • figsizeJupyter Notebook에 맞게 최적화 되어 있기는 하지만, 수정할 수 있다.
%matplotlib inline
import matplotlib.pylab as plt

plt.rcParams["figure.figsize"] = (14,4)
plt.rcParams['lines.linewidth'] = 2
plt.rcParams['lines.color'] = 'r'
plt.rcParams['axes.grid'] = True 
  • 그리고 마지막으로 for-loop 활용하는 시각화를 작성한다.
for fea in feature_names:
  data = df.copy()
  # iris.sepal_length[:20].plot(kind='bar', rot=0)
  data[fea].plot(kind='hist', rot=0)
  plt.xlabel(fea)
  plt.title(fea)
  plt.show()

png

Python for loops in different ways

강의 홍보

I. 개요

  • 여러 형태의 반복문을 배우고 실습한다.
  • 한줄로 작성하는 반복문을 배우고 실습한다.

II. For Loop Basic Syntax

  • 파이썬의 기본 문법은 아래와 같다.
for <변수> in <iterable>:
    <코드>
  • 여기에서 iterable의 개념은 listtuple을 의미한다.
  • 간단하게 for_loop 코드를 작성해보자.
    • 우선, A라는 리스트 객체를 작성한다.
    • for_loop를 활용해서 리스트 안에 있는 것을 하나씩 출력한다.
A = ["철수", "영희", "길동"]
for i in A:
  print(i)
철수
영희
길동

(1) Iterables

  • Iteration을 한국어로 번역하면 되풀이다.
  • 그런데, 어떤 데이터 유형이 되풀이를 할 수 있을가?
    • ListTuple이 되풀이가 될 수 있는 소재인 것은 확실하다.
  • 어떤 객체(=Object)가 있을 때, 이 객체가 iterable 한것인지, 또는 아닌지 확인하는 함수(iter())도 있다.
print(iter("ABC"))
<str_iterator object at 0x7f2464faeb00>
print(iter(["A", "B", "C"]))
<list_iterator object at 0x7f2464faedd8>
print(iter(("A", "B", "C")))
<tuple_iterator object at 0x7f2464faedd8>
print(iter({"A": 1, "B": 3, "C": 3}))
<dict_keyiterator object at 0x7f2464fdd458>
  • 그런데, 수치형의 경우에는 iteration이 적용되지 않는다.
iter(100)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-48-f3bbc5ecfc9b> in <module>()
----> 1 print(iter(100))

TypeError: 'int' object is not iterable
iter(3.14)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-eb85da4c3f57> in <module>()
----> 1 iter(3.14)

TypeError: 'float' object is not iterable
  • 단일 수치형 데이터를 제외하고는 사실상 모든 데이터가 iterable의 성질을 가지고 있다.

(2) next()

  • next()iterator에서의 next value를 의미한다.
  • 다음 코드를 확인해보자.
A = ["철수", "영희", "길동"]
iterable = iter(A)
iterable

<list_iterator at 0x7f2464fb7dd8>

If else, and more

강의 홍보

I. 개요

  • 조건문에 대해 배우고 실습하는 시간을 갖는다.
  • else와 elif에 대해 배우고 실습한다.
  • 한줄로 작성하는 if_else에 대해 배우고 실습한다.

II. If 조건문 소개

  • Excel을 배운 사람이라면 누구나 아는 문법이다.
    • 다만, 위 문법을 파이썬 언어에 맞게 변형한 것이다.
if <조건=True>:
  <코드1>
  <코드2>

(1) 언제 실행되는가?

  • 위 구문의 뜻이 무엇인가?

About Dictionaries

강의 홍보

I. 개요

  • 이번 시간부터 본격적으로 파이썬의 기초 자료형에 대해 간단한 튜토리얼을 준비했다.
  • 데이터 분석과는 큰 관계가 없을 수 있지만, 데이터 정제 할 때, 도움이 되기도 한다.
  • 그 중에서 면접의 단골질문과 같은 Dictionary에 대해 나누는 시간을 가졌다.

II. Dictionary의 기본적인 특징

  • Dictionary는 영어 원뜻 그대로 사전을 생각하면 된다.
  • DictionaryList와 유사한 부분이 많다.
    • List와 같이 Mutable이라는 뜻을 포함한다.
    • List와 같이 다른 Dictionary, list 등을 포함시킬 수 있다.
  • 차이점은 원소에 대한 접근방법의 차이다.
    • List에서 각 원소에 대한 접근법은 index을 활용한다.
    • Dictionary에서 각 원소에 대한 접근법은 keys에 의해 접근한다.

III. Dictionary 정의

  • 로고사진처럼, Dictionarykey-value로 구성 되어 있다.
  • Dictionary를 정의하는 방법에는 여러가지가 있다.

(1) 기본 { }를 활용한 방법

  • 기본적인 문법은 아래와 같다.
d = {
    <>: <>,
    <>: <>,
      .
      .
      .
    <>: <>,
}
  • 간단하게 국내 야구팀을 Dictionary 형태로 만들어보자.
KOR_team1 = {
    "인천"  : "SK", 
    "서울1" : "LG", 
    "서울2" : "두산", 
    "창원"  : "NC",
    "광주"  : "기아",
    "대구"  : "삼성",
    "대전"  : "한화",
    "부산"  : "롯데",
    "수원"  : "KT",
    "고척"  : "키움",
}
KOR_team1
{'고척': '키움',
 '광주': '기아',
 '대구': '삼성',
 '대전': '한화',
 '부산': '롯데',
 '서울1': 'LG',
 '서울2': '두산',
 '수원': 'KT',
 '인천': 'SK',
 '창원': 'NC'}

(2) 내장함수 dict()를 활용하는 방법

  • key-value를 활용하는데, 이 때 tuple 형태로 작성한다.
d = dict([
    (<>, <>),
    (<>, <값),
      .
      .
      .
    (<>, <>)
])
  • 똑같이 야구팀을 작성한다.
KOR_team2 = dict([
  ("인천", "SK"), 
  ("서울1", "LG"), 
  ("서울2", "두산"), 
  ("창원", "NC"), 
  ("광주", "기아"), 
  ("대구", "삼성"), 
  ("대전", "한화"), 
  ("부산", "롯데"), 
  ("수원", "KT"), 
  ("고척", "키움")
])

KOR_team2
{'고척': '키움',
 '광주': '기아',
 '대구': '삼성',
 '대전': '한화',
 '부산': '롯데',
 '서울1': 'LG',
 '서울2': '두산',
 '수원': 'KT',
 '인천': 'SK',
 '창원': 'NC'}

(3) dict with spring

  • dict() 함수 안에 문자열 변수를 입력하는 형태로 코드를 작성한다.
KOR_team3 = dict(
  인천 = "SK", 
  서울1 = "LG", 
  서울2 = "두산", 
  창원 = "NC", 
  광주 = "기아", 
  대구 = "삼성", 
  대전 = "한화", 
  부산 = "롯데", 
  수원 = "KT", 
  고척 = "키움" 
)

KOR_team3
{'고척': '키움',
 '광주': '기아',
 '대구': '삼성',
 '대전': '한화',
 '부산': '롯데',
 '서울1': 'LG',
 '서울2': '두산',
 '수원': 'KT',
 '인천': 'SK',
 '창원': 'NC'}
  • 실제 Dictionary 형태로 정의가 되었는지 확인해본다.
print(type(KOR_team1))
print(type(KOR_team2))
print(type(KOR_team3))
<class 'dict'>
<class 'dict'>
<class 'dict'>

IV. Dictionary 접근법

  • Dictionary 원소 접근법은 indexing이 아니라 key값에 의해 결정된다.
print(KOR_team1['인천'])
print(KOR_team1['부산'])
SK
롯데
  • 만약에 전주에 새로운 야구팀(현대)이 생겼다고 가정하자.
  • 추가하는 소스코드는 아래와 같다.
KOR_team1['전주'] = "현대"
KOR_team1
{'고척': '키움',
 '광주': '기아',
 '대구': '삼성',
 '대전': '한화',
 '부산': '롯데',
 '서울1': 'LG',
 '서울2': '두산',
 '수원': 'KT',
 '인천': 'SK',
 '전주': '현대',
 '창원': 'NC'}
  • 전주: 현대가 추가된 것을 확인할 수 있다.
  • 이번에는 방금 추가한 전주: 현대를 삭제하도록 하자. (del) 함수 사용
del KOR_team1['전주']
KOR_team1
{'고척': '키움',
 '광주': '기아',
 '대구': '삼성',
 '대전': '한화',
 '부산': '롯데',
 '서울1': 'LG',
 '서울2': '두산',
 '수원': 'KT',
 '인천': 'SK',
 '창원': 'NC'}
  • 정상적으로 삭제가 된 것을 확인할 수 있다.

V. Dictionary Using Integer

  • 이전까지 접근한 것은 문자를 입력해서 접근했다.
  • Integer로 활용하는 방법은 없을까?
dic = {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
dic
{0: 'a', 1: 'b', 2: 'c', 3: 'd'}
print(dic[0])
print(dic[1])
a
b
  • 그러나 주의해야 하는 것은 diclist가 아니다.
  • 즉, list에서 할 수 있었던, slicing이나 append를 사용할 수 없다.
    • 관련 에러 몇개를 확인해보자.
dic.append('e')
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-20-8bfa5988d009> in <module>()
----> 1 dic.append('e')


AttributeError: 'dict' object has no attribute 'append'
  • AttributeError: 'dict' object has no attribute 'append' 이 뜻이 함의하는 것은 dictionary에는 append라는 속성값이 없다는 뜻이다.
dic[0:2]
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-21-82c17d59c309> in <module>()
----> 1 dic[0:2]


TypeError: unhashable type: 'slice'
  • 마찬가지로 list에서 작동했던 slice는 여기에서는 존재하지 않는다.

VI. Dictionary와 관련된 여러 함수 소개

  • Dictionary와 함께 사용되면 좋은 함수들을 간단하게 소개 한다.

(1) d.clear()

  • 먼저 아래 코드를 확인해보자.
dic = {'A': 1, 'B': 2, 'C': 3}
dic
{'A': 1, 'B': 2, 'C': 3}
  • clear() 함수 적용 뒤 결과값을 확인해보자.
dic.clear()
dic
{}
  • 결과값을 확인해보니 모두 삭제된 것을 확인할 수 있다.

(2) d.get()

  • get()함수는 key값을 활용해서 value값을 가져오는 함수다.
  • 소스코드를 통해 확인하자.
dic = {'A': 1, 'B': 2, 'C': 3}
print(dic.get('B'))
print(dic.get('Z'))
2
None
  • .get('B')에 해당하는 Dictionary값이 존재하기 때문에 2를 반환한다.
  • .get('Z')에 해당하는 Dictionary값이 존재하지 않기 때문에 None을 반환한다.
    • 그런데 None을 반환하기 보다 특정 숫자 또는 문자로 출력하고 싶다면 다음과 같이 입력하면 된다.
print(dic.get('z', 0))
print(dic.get('z', "없음"))
0
없음

(3) d.keys()

  • Dictionarykeyvalue로 구성되어 있는데, keys()의 뜻은 현재 구성되어 있는 Dictionary에서 keys()dict_keys 형태로 반환한다.
    • 이 때, list로 변환을 하려면 list()를 활용하면 된다.
dic = {'A': 1, 'B': 2, 'C': 3}
print(dic.keys())
print(list(dic.keys()))
dict_keys(['A', 'B', 'C'])
['A', 'B', 'C']

(4) d.values()

  • keys()를 활용하여 key를 반환했던 것처럼, values()를 활용하여 value를 진행하자.
    • 코드는 위와 동일하다. 다만, 함수만 바꾼다.
dic = {'A': 1, 'B': 2, 'C': 3}
print(dic.values())
print(list(dic.values()))
dict_values([1, 2, 3])
[1, 2, 3]
  • 그 외에도 pop(), popitem(), update()를 활용법을 익혀본다.

VII. Reference

w3schools. Python Dictionaries. Retrieved June 20, 2020, from https://www.w3schools.com/python/python_dictionaries.asp

The difference betwen Lists and Tuples in Python

강의 홍보

I. 개요

  • 이번 시간부터 본격적으로 파이썬의 기초 자료형에 대해 간단한 튜토리얼을 준비했다.
  • 데이터 분석과는 큰 관계가 없을 수 있지만, 데이터 정제 할 때, 도움이 되기도 한다.
  • 그 중에서 면접의 단골질문과 같은 Lists & Tuple에 대해 나누는 시간을 가졌다.

II. Lists

  • 먼저 Lists[] 형태로 정의가 된다.
alphabet = ['A', 'B', 'C', 'D']
print(alphabet)
['A', 'B', 'C', 'D']
  • 코드는 간단하다. 그러나 함의하고 있는 내용은 다음과 같다.
    • List는 정렬(ordered)되었다.
    • List는 다양한 형태의 데이터 유형을 담을 수 있다.
    • List안에 있는 값은 인덱스로 접근한다.
    • List안에 또다른 List를 담을 수 있다.
    • List는 변하기 쉽다.
    • List는 동적이다.

(1) List는 정렬(ordered)되었다.

  • 우선 코드로 확인하자.
a1 = [1, 2, 3, 4]
a2 = [2, 3, 4, 1]

a1 == a2
False
a1 is a2
False
[1, 2, 3, 4] == [2, 3, 4, 1]
False
  • 일련의 코드는 a1a2가 같지 않다는 것을 프로그래밍적으로 증명한 것이다.
    • 좀 더 쉽게 표현하면 List안에 있는 값은 순서가 있다는 뜻이다.

(2) List는 다양한 형태의 데이터 유형을 담을 수 있다.

  • List의 편리성이기도 하지만, 분석시에는 데이터프레임으로 변환할 때 큰 애로사항이 되기도 한다.
  • 우선, 코드로 확인해보자.
multi_values = [11.1, 'foo', 3, 5, 'bar', True, False, 3.1245]
print(multi_values)
[11.1, 'foo', 3, 5, 'bar', True, False, 3.1245]
  • 또한, List는 다양한 함수, class, 심지어는 모듈도 담을 수 있다.
float
float
len
<function len>
def temp():
  pass
temp
<function __main__.temp>
import math
math
<module 'math' (built-in)>
multi_objects = [float, len, temp, math]
multi_objects
[float, <function len>, <function __main__.temp>, <module 'math' (built-in)>]

(3) List안에 있는 값은 인덱스로 접근한다.

  • 다음 그림이 인덱스로 접근하는 기본적인 방법이다.
    • 참고로 또다른 분석 언어인 R0이 아닌 1부터 시작한다.
  • 소스코드로 빠르게 확인해보자.
temp = ["A", "B", "C", "D", "E"]
temp[0]
'A'
temp[1]
'B'
temp[4]
'E'
  • 그런데, Negative List 형태로도 접근할 수 있다.
    • -1, -2와 같은 형태로 접근하는 것이다.
  • 코드를 통해 확인해보자.
temp[-1]
'E'
temp[-4]
'B'
temp[-5]
'A'
  • 슬라이싱을 활용한 인덱스 접근법도 있다.
    • temp[m:n] 형태로 From M to N으로 접근한다.
  • 코드를 통해서 확인해보자.
temp[0:5]
['A', 'B', 'C', 'D', 'E']
temp[2:4]
['C', 'D']
temp[-5:-1]
['A', 'B', 'C', 'D']
temp[-5:]
['A', 'B', 'C', 'D', 'E']
  • 이 외에도, 슬라이싱 기법을 활용한 다양한 접근법이 있다. 스택오버플로우의 문서를 확인해보면 보다 더 많은 정보를 얻을 수 있다.

(4) List안에 또다른 List를 담을 수 있다.

  • List안에 다양한 객체가 들어가 있음을 확인했다.
  • 그런데, List안에 또 다른 List가 들어갈 수도 있다.