1. Pandas 실습
판다스의 개발 환경은 Jupyter Notebook으로 진행한다.
왜 Jupyter Notebook인가 하면 쉘마다 실습이 가능하기 때문에 시각화할 수 있기 때문이다.
// Conda의 실행파일이 인식되도록 함
export PATH="/Users/suyeon/anaconda3/bin:$PATH"
// 인식됨을 확인함
conda list
// Conda 버전 업데이트
conda update conda
// Conda 가상환경 생성
conda create --nmae pandas_course
// Conda 환경을 활성화할 수 있도록 필요한 설정을 현재 셸에 적용하는 명령어
source /Users/suyeon/anaconda3/etc/profile.d/conda.sh
// Conda 가상환경 활성화
conda activate pandas_course
// ipkernel 설치 : 가상환경을 Jupyter Notebook에서 사용하려면 ipkernel을 설치해야 함
pip3 install ipykernel
// 가상환경을 JuypyterNotebook에 추가하기
python -m ipykernel install --user --name myenv --display-name "my Env"
// Conda 가상환경 관리
conda env list
데이터 프레임
import pandas as pd
# Series 생성, index 값을 주게 되면 0, 1, 2가 아닌 명시적 기준열이 생기는 것이다.
sample = pd.Series(["쿠키", "초코", 2], index = ["종류", "맛", "갯수"])
# 데이터 프레임의 타입은 각각은 다를 수 있지만 표시될 때에는 넓은 범위의 타입으로 표시된다는 특징이 있다.
sample.apply(type)
'''
종류 <class 'str'>
맛 <class 'str'>
갯수 <class 'int'>
'''
data = {
'이름': ['철수', '영희'],
'나이': [20, 30],
'직업': ['학생', '의사'] ;
}
df = pd.DataFrame(data)
# 깔끔한 형태로 나오게 된다. (Series가 결합된 진정한 데이터 프레임 형태이기 때문)
print(df)
특정 인덱스로 기준점을 세울 수도 있게 된다.
이때 inplace 옵션을 주어야 df 자체가 바뀌게 된다.
df.set_index("이름", inplace=True)
df[["나이", "직업"]] -> "나이", "직업" 두 series가 결합되어 DataFrame 형태로 나온다.
2. Numpy
Numpy의 주요 특징
Numpy 연산자의 특징
복합 대입 연산 (arr //= 2) 은 그 자리에서 값을 수정하는 것이며
직접 연산 (arr = arr // 2) 은 계산 후 그 자리에 할당해주는 것임
따라서 만약 int 나눗셈 연산 후 float가 반환된다면 복합 대입 연산에서는 에러가 나오는 반면 직접 연산은 에러가 나타나지 않게 된다.
왜냐? int 자리에 float 값을 넣어주려 하기 때문이다.
Numpy의 Atribute
을 알아보기 전에 계속 나오는 형상에 대해 간단히 알아보고 가겠다.
형상
예시를 들어서 설명해보겠다
arr1 = np.array([1, 2, 3, 4, 5])
이 경우에는 1차원 배열이며 원소의 개수는 5개이다.
따라서 형상은 (5,) 이다.
그렇다면
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
이 경우는 어떻겠는가?
이 경우에는 2차원의 배열이며, 2행 3열의 형태를 띄고 있다.
따라서 형상은 (2, 3)이다.
3차원의 경우에는 어떨까?
arr3 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
2면 2행 3열의 형태로 되어있다.
때문에 형상은 (2, 2, 3) 이다.
면 / 행 / 열 사이의 우선 순위는 존재하지 않지만 형상을 작성하기 위해서 우선 순위가 존재한다고 간주해 이해하니 더 수월했다.
그래서 정리하자면 형상 표현은
본격적인 Numpy의 Attribute를 살펴보겠다.
배열의 변환 Method
배열의 연산
1. np.array().mean()
배열의 모든 속성/메서드를 확인하고 싶다면?
-> dir(np.array())
배열 채워넣기
연산
arr1 = np.array([1,2,3,4,5])
arr2 = np.array([6,7,8,9,10])
arr3 = np.array([11,12])
arr4 = np.array([13]) # 브로드 캐스팅 확인 용도
result1 = arr1 + arr2 # [7,9,11,13,15]
result2 = arr1 + arr3 # 에러가 뜸 -> 브로드캐스팅 조건에 맞지 않았기 때문임
result4 = arr1 + arr4 # [14, 15, 17, 18] -> 자동 행렬 덧셈을 해줌
np.add(arr1, arr4, out = result) # arr1과 arr4의 행렬 덧셈 결과가 result로 나옴, result는 미리 선언되어 있어야 함
np.subtract(arr1,arr2) # arr1 에 arr2를 뺌
np.multiple(arr1, arr2) # arr1에 arr2를 곱함
np.floor_divide(arr1, arr2) # arr1에 arr2를 나눔 (소수점 버림)
np.mod(arr1, arr2) # arr1에 arr2를 나눈 나머지를 반환함
np.empty_like(arr1) # arr1 형상을 가진 빈 np array가 생성이 됨
arr1 = np.array([1, 2, 3]) # 형싱 : (3,)
arr2 = np.array([[10], [20], [30]]) # 형상 : (3,1)
broadcasting_result = arr1 + arr2
print(broadcasting_result.shape) # (3,3)
'''
# broadcasting_result 형태
array([[11, 12, 13],
[21, 22, 23],
[31, 32, 33]])
'''
예시문제를 풀어서 체득해보겠다
(문제 출처 : Programmers)
문제 1.

🧚
만약 numpy의 array가 아니라 그냥 array라면은 2배 연산을 진행해 준 후에 직접 모든 인덱스에 대입해주어야 하는 작업이 필요하겠다.
하지만 numpy의 array는 위 상황을 직접 배열에 2배를 해주는 것만으로도 해결할 수 있다. (브로드캐스팅)
📌
import numpy as np
def solution(arr, y1, x1, y2, x2):
arr[y1:y2+1, x1:x2+1] = arr[y1:y2+1, x1:x2+1] * 2
answer = arr
return answer
문제 2.

🧚
np의 사용법을 안다면 쉽게 풀 수 있는 문제이다
내적 연산을 하려면 np.dot(배열, transform 할 배열)
📌
import numpy as np
def solution(x, w, b):
answer = np.dot(x,w) + b
return answer
문제 3.

🧚
np.array() 형태로 들어오는 원소들의 형태에 유의하여 작성해야 한다.
해당 문제에서는 인덱스를 return 값에 포함시켜야 하기 때문에 for문에 원소 직접 접근이 아닌 인덱스 접근을 해야 한다.
📌
import numpy as np
def solution(info):
for i in range(len(info[0]):
if info[0, i] <= 150 or info[0,i] >=195 or info[1,i] >= 140:
answer.append(i)
return answer
문제 4.

🧚
여기에서 핵심은 "A와 arr의 행렬곱이 가능하다"는 조건이다.
행렬곱이 가능한 조건은 아래와 같다.
왼쪽 행렬 X 오른쪽 행렬이 있다고 했을 때
왼쪽 행렬의 열의 수와 오른쪽 행렬의 행의 수가 동일할 때이다.
왼쪽 행렬의 열의 수는 len(A[0])이고
오른쪽 행렬의 행의 수는 len(arr)가 되겠다.
또한 행렬 곱을 진행하기 위해 np.dot() 를 사용했다.
📌
import numpy as np
def solution(arr_list):
a = np.array([[0]])
for arr in arr_list:
if len(a[0]) == len(arr):
a = np.dot(a + 1, arr * 2)
answer = a
return answer
문제 5.

🧚
np.array() 형태로 들어오는 파라미터를 최대한 활용하는 것이 이 문제의 핵심이 되겠다.
들어오는 img의 각 열의 형태와 동일하게 return 하기 때문이다.
📌
import numpy as np
def solution(img):
h = len(img)
w = len(img[0])
r = img[:,:,0]
g = img[:,:,1]
b = img[:, :,2]
return 0.3 * r + 0.5 * g + 0.2 * b