일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 파견
- 모던 자바스크립트 딥 다이브
- 인가
- 로만
- JVM
- 직렬화
- JDK
- 제네릭
- 할당
- implements
- 메모리
- Roman
- JSON
- LeetCode
- 비전공
- 딥다이브
- 빌트인객체
- jre
- javascript
- Two
- java
- 자바
- 릿코드
- integer
- 이냐
- SUM
- 제너릭
- strict mode
- 모던자바스크립트
- 부탁드립니다
- Today
- Total
AnnSEo.log
[파이썬 머신러닝 완벽가이드] CH01 본문
머신러닝 : 애플리케이션을 수정하지 않고도 데이터 기반으로 패턴을 학습하고 결과를 예측하는 알고리즘 기법
예측 분석(Predictive Analysis)으로 재편중
머신러닝
- 지도학습(Supervised Learning)
분류, 회귀, 추천 시스템, 시각/음성 감지/인지, 텍스트 분석, NLP
- 비지도학습(Un-supervised Learning)
클러스터링, 차원 축소, 강화학습
- 강화학습(Reinforment Learning)
머신러닝의 가장 큰 단점은 데이터에 매우 의존적이라는 것(Garbage In, Garbage out)
파이썬과 R을 기반으로 머신러닝 프로그램을 작성하는데, 이 책에서는 파이썬 이용
- 쉽고 뛰어난 개발 생산성
- 많은 라이브러리
- 뛰어난 확장성, 유연성, 호환성
- 결합된 다양한 애플리케이션 개발 가능
- 엔터프라이즈 아키텍쳐로 확장, 마이크로서비스 기반 실시간 연계 등으로 확산 가능
파이썬 머신러닝 주요 패키지
- 머신러닝 패키지 : 사이킷런(Scikit-Learn)
- 행렬/선형대수/통계 패키지 : 넘파이(NumPy), 사이파이(SciPy)
- 데이터 핸들링 : 판다스
- 시각화 : 맷플롯립(Matplotlib), 시본(Seaborn)
그 외 주피터 노트북(Jupyter Notebook) - IPython 툴(대화형 툴)
공부는 넘파이와 판다스가 머신러닝 예제와 어떻게 결합되어 어떻게 데이터 가공에 사용되는지를 인지하는 방향으로!
- 넘파이
머신러닝 주요 알고리즘은 선형대수와 통계 등에 기반하고, Numerical Python을 의미하는 NumPy는 선형대수 기반 프로그램을 쉽게 만들 수 있게 지원함. 배열 연산 지원
C/C++과 같은 저수준 언어 기반 호환 API를 제공
파이썬 언어 자체의 성능 제약으로 인해, 수행 성능이 중요한 부분은 C/C++ 기반 코드로 작성하고 이걸 넘파이에서 호출하는 방식으로 쉽게 통합할 수 있다. -> 구글의 텐서플로가 이런 방식으로 배열 연산 수행 속도를 개선하고 넘파이와도 호환될 수 있게 작성됨
-> 많은 머신러닝 알고리즘이 넘파이 기반으로 작성돼 있고, 알고리즘의 입력 데이터와 출력 데이터를 넘파이 배열 타입으로 사용함
ndarray
넘파이 기반 데이터 타입, 다차원 배열을 쉽게 생성하고 다양한 연산 수행 가능
np.array() : 다양한 인자를 입력받아 ndarray로 변환함
ndarray.shape : ndarray의 차원과 크기를 튜플tuple 형태로 나타내줌
array.ndim : array의 차원
ndarray 의 데이터 타입
- int(8bit, 16bit, 32bit)
- unsigned int(8bit, 16bit, 32bit)
- float(16bit, 32bit, 64bit, 128bit)
- complex 타입(더 큰 숫자 값이나 정밀도)
array1 = np.array([1, 2, 3])
print('array1 type:', type(array1))
print('array1 array 형태:', array1.shape)
# array1 type: <class 'numpy.ndarray'>
# array1 array 형태: (3,)
array2 = np.array([[1, 2, 3], [2, 3, 4]])
print('array2 type:', type(array2))
print('array2 array 형태:', array2.shape)
# array2 type: <class 'numpy.ndarray'>
# array2 array 형태: (2, 3)
array3 = np.array([[1, 2, 3]])
print('array3 type:', type(array3))
print('array3 array 형태:', array3.shape)
# array3 type: <class 'numpy.ndarray'>
# array3 array 형태: (1, 3)
print('array1: {:0}차원, array2: {:1}차원, array3: {:2}차원'.format(array1.ndim, array2.ndim, array3.ndim))
한 ndarray 안에 int와 float가 함께 있을 수 없음
만약 데이터 유형이 섞인 리스트를 ndarray로 변경하면 데이터 크기가 더 큰 타입으로 형 변환을 일괄 적용한다.
array.dtype으로 속성 확인
array.astype()으로 ndarray 내 데이터 값의 타입 변경도 가능 - 보통 메모리 절약을 위해 사용(ndarray 만들 때 메모리가 많이 사용되고, 데이터 타입이 float이라면 int형으로 바꿔서 메모리를 절약할 수 있음)
list1 = [1, 2, 3]
print(type(list1))
array1 = np.array(list1)
print(type(array1))
print(array1, array1.dtype)
# <class 'list'>
# <class 'numpy.ndarray'>
# [1 2 3] int32
list2 = [1, 2, 'test']
array2 = np.array(list2)
print(array2, array2.dtype)
list3 = [1, 2, 3.0]
array3 = np.array(list3)
print(array3, array3.dtype)
# ['1' '2' 'test'] <U11 // 문자열로 형 변환
# [1. 2. 3.] float64 // 실수로 형 변환
특정 크기와 차원을 가진 ndarray를 연속값이나 0 또는 1로 초기화해 쉽게 생성해야 할 필요가 있는 경우가 발생할 수 있음
→ arange(), zeros(), ones() 를 이용해 ndarray를 생성
- arange() : 0부터 함수 인자 값 - 1까지의 값을 순차적으로 ndarray의 데이터 값으로 변환해줌
- zero() : 함수 인자로 튜플 형태의 shape 값을 입력하면 모든 값을 0으로 채운 해당 shape를 가진 ndarray를 반환한다.
- ones() : 값을 1로 채움(제로와 비슷한데), dtype을 안정하면 float64 데이터로 채움
sequence_array = np.arange(10)
print(sequence_array)
print(sequence_array.dtype, sequence_array.shape)
# [0 1 2 3 4 5 6 7 8 9]
# int32 (10,)
zero_array = np.zeros((3, 2), dtype='int32')
print(zero_array)
print(zero_array.dtype, zero_array.shape)
one_array = np.ones((3,2))
print(one_array)
print(one_array.dtype, one_array.shape)
# [[0 0]
# [0 0]
# [0 0]]
# int32 (3, 2)
# [[1. 1.]
# [1. 1.]
# [1. 1.]]
# float64 (3, 2)
- reshape() : ndarray의 차원과 크기를 변경
- 지정된 사이즈로 변경이 불가능하면 오류 발생
- 인자로 -1을 적용하는 경우에 효율적
- -1을 인자로 사용하면 원래 ndarray와 호환되는 새로운 shape로 변환해준다.
- -1 인자는 reshape(-1, 1)의 형태로 많이 사용 : 여러 개의 로우를 가지되, 반드시 1개의 컬럼을 가진 ndarray로 변환됨을 보장함
array5 = np.arange(10)
print('array5:\n', array5)
array6 = array5.reshape(2, 5)
print('array6:\n', array6)
array7 = array5.reshape(5, 2)
print('array7:\n', array7)
array5:
[0 1 2 3 4 5 6 7 8 9]
array6:
[[0 1 2 3 4]
[5 6 7 8 9]]
array7:
[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
array8 = np.arange(10)
print(array8)
array9 = array8.reshape(-1, 5)
print('array9 shape:', array9.shape)
array10 = array8.reshape(5, -1)
print('array10 shape:', array10.shape)
# [0 1 2 3 4 5 6 7 8 9]
# array9 shape: (2, 5)
# array10 shape: (5, 2)
# 여기서 array9 같은 경우 행은 -1이고 열은 5로 고정하되,
# array8이 10개의 데이터가 들어있으므로 행은 자동으로 5에 맞게 2개를 넣어주게!
# 고정된 5개의 컬럼에 맞는 로우를 자동으로 새롭게 생성해 변환하라는 뜻
array11 = np.arange(8)
array3d = array11.reshape((2, 2, 2))
print('array3d:\n', array3d.tolist())
# 3차원 ndarray를 2차원 ndarray로 변환
array12 = array3d.reshape(-1, 1)
print('array12:\n', array12.tolist())
print('array12 shape:', array12.shape)
# 1차원 ndarray를 2차원 ndarray로 변환
array13 = array11.reshape(-1, 1)
print('array13:\n', array13.tolist())
print('array13 shape:', array13.shape)
array3d:
[[[0, 1], [2, 3]], [[4, 5], [6, 7]]]
array12:
[[0], [1], [2], [3], [4], [5], [6], [7]]
array12 shape: (8, 1)
array13:
[[0], [1], [2], [3], [4], [5], [6], [7]]
array13 shape: (8, 1)
- 넘파이의 ndarray의 데이터 세트 만들기 - 인덱싱
- 특정한 데이터만 추출
- 단일 값 추출
- 슬라이싱
- : 기호 사용해서 연속한 데이터 슬라이싱
- 단일 값 추출을 제외한 슬라이싱, 팬시 인덱싱, 불린 인덱싱으로 추출한 모든 데이터 세트는 ndarray 타입이다.
- ':' 기호 앞에 시작 인덱스 생략하면 자동으로 맨 처음 인덱스인 0으로 간주
- 종료 인덱스 생략시 자동으로 맨 마지막 인덱스로 간주
- : 기호 앞/뒤에 시작/종료 인덱스 생략시 자동으로 맨 처음/맨 마지막 인덱스로 간주
- 특정한 데이터만 추출
# 1부터 9까지 1차원 ndarray 생성
array14 = np.arange(start=1, stop=10)
print('array14:', array14)
# index는 0부터 시작하므로 array14[2]는 3번째 index 위치의 데이터값을 의미
value = array14[2]
print('value:', value)
print(type(value))
array14: [1 2 3 4 5 6 7 8 9]
value: 3
<class 'numpy.int32'>
array1 = np.arange(start=1, stop=10)
array4 = array1[:3]
print(array4)
array5 = array1[3:]
print(array5)
array6 = array1[:]
print(array6)
[1 2 3]
[4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3, 3)
print('array2d:\n', array2d)
print('array2d[0:2, 0:2]\n:', array2d[0:2, 0:2])
print('array2d[1:3, 0:3]\n:', array2d[1:3, 0:3])
print('array2d[1:3, :]\n:', array2d[1:3, :])
print('array2d[:, :]\n:', array2d[:, :])
print('array2d[:2, 1:]\n:', array2d[:2, 1:])
print('array2d[:2, 0]\n:', array2d[:2, 0])
array2d:
[[1 2 3]
[4 5 6]
[7 8 9]]
array2d[0:2, 0:2]
: [[1 2]
[4 5]]
array2d[1:3, 0:3]
: [[4 5 6]
[7 8 9]]
array2d[1:3, :]
: [[4 5 6]
[7 8 9]]
array2d[:, :]
: [[1 2 3]
[4 5 6]
[7 8 9]]
array2d[:2, 1:]
: [[2 3]
[5 6]]
array2d[:2, 0]
: [1 4]
행(row) → axis0
열(column) → axis1
- 팬시 인덱싱(Fancy Indexing)
- 리스트나 ndarray로 인덱스 집합을 지정하면 해당 위치의 인덱스에 해당하는 ndarray를 반환하는 인덱싱 방식
- 불린 인덱싱(Boolean Indexing)
- 조건 필터링과 검색을 동시에 할 수 있어 자주 사용되는 인덱싱 방식
- ndarray의 필터링 조건을 []을 기재
- False 값을 무시하고 True 값에 해당하는 인덱스값만 저장함(값을 저장하는게 아니라 인덱스를 저장한다)
- 저장된 인덱스 데이터 세트로 ndarray 조회
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3, 3)
array3 = array2d[[0,1], 2]
print('array2d[[0,1], 2] => ', array3.tolist())
array4 = array2d[[0,1], 0:2]
print('array2d[[0, 1], 0:2] =>', array4.tolist())
array5 = array2d[[0,1]]
print('array2d[[0,1]] =>', array5.tolist())
array2d[[0,1], 2] => [3, 6]
array2d[[0, 1], 0:2] => [[1, 2], [4, 5]]
array2d[[0,1]] => [[1, 2, 3], [4, 5, 6]]
array1d = np.arange(start=1, stop=10)
array3 = array1d[array1d > 5]
print('array1d > 5 불린 인덱싱 결과 값 :', array3)
array1d > 5 불린 인덱싱 결과 값 : [6 7 8 9]
array1d > 5
# 넘파이 ndarray 객체에 조건식 할당하면 false, true로 이뤄진 ndarray 객체가 반환됨
# false는 무시하고 true 값이 있는 위치 인덱스 값으로 자동 변환해
# 해당하는 인덱스 위치의 데이터만 반환
array([False, False, False, False, False, True, True, True, True])
- 행렬을 정렬하는 대표적인 방법
- np.sort()
- 원 행렬은 그대로 유지한 채 원 행렬의 정렬된 행렬을 반환
- ndarray.sort()
- 원 행렬 자체를 정렬한 형태로 변환하고 반환 값은 None이다.
- np.sort()
- 내림차순으로 정렬하려면 [::-1]을 적용
- 정렬된 행렬의 인덱스를 반환
- argsort() - 원본 행렬 자체를 바꾸진 않음, 행렬을 정렬하고 그 인덱스 추출해서 반환
org_array = np.array([3, 1, 9, 5])
print('원본:', org_array)
sort_array1 = np.sort(org_array)
print('np.sort() 호출 후 반환된 정렬 행렬 :', sort_array1)
print('np.sort() 호출 후 반환된 원본 행렬 :', org_array)
sort_array2 = org_array.sort()
print('org_array.sort() 호출 후 반환 행렬:', sort_array2)
print('ort_array.sort() 호출 후 원본 행렬:', org_array)
원본: [3 1 9 5]
np.sort() 호출 후 반환된 정렬 행렬 : [1 3 5 9]
np.sort() 호출 후 반환된 원본 행렬 : [3 1 9 5]
org_array.sort() 호출 후 반환 행렬: None
ort_array.sort() 호출 후 원본 행렬: [1 3 5 9]
sort_array1_desc = np.sort(org_array)[::-1]
print('내림차순으로 정렬:', sort_array1_desc)
내림차순으로 정렬: [9 5 3 1]
array2d = np.array([[8, 12], [7, 1]])
sort_array2d_axis0 = np.sort(array2d, axis = 0)
print('로우 방향으로 정렬:\n', sort_array2d_axis0)
sort_array2d_axis1 = np.sort(array2d, axis=1)
print('컬럼 방향으로 정렬:\n', sort_array2d_axis1)
로우 방향으로 정렬:
[[ 7 1]
[ 8 12]]
컬럼 방향으로 정렬:
[[ 8 12]
[ 1 7]]
org_array = np.array([3,1,9,5])
sort_indices = np.argsort(org_array)
print(type(sort_indices))
print('행렬 정려 시 원본 행렬의 인덱스:', sort_indices)
<class 'numpy.ndarray'>
행렬 정려 시 원본 행렬의 인덱스: [1 0 3 2]
name_array = np.array(['존', '마이크', '사라', '케이트', '사무엘'])
score_array = np.array([78, 95, 84, 98, 88])
sort_indices_asc = np.argsort(score_array)
print(name_array[sort_indices_asc])
['존' '사라' '사무엘' '마이크' '케이트']
- ndarray는 RDBMS의 TABLE 컬럼이나 판다스 DataFrame 칼럼과 같은 메타 데이터를 갖을 수 없음
- 고로 실제 값과 그 값이 뜻하는 메타 데이터를 별도의 ndarray로 각각 가져야 한다.
- 선형대수 연산 - 행렬 내적과 전치 행렬 구하기
- 행렬 내적(행렬 곱) : np.dot()
- 전치 행렬 : 행과 열을 교환한 원소로 구성한 행렬을 그 행렬의 전치 행렬이라고 함. transpose() 이용
# 행렬 내적(행렬 곱)
A = np.array([[1, 2, 3], [4, 5, 6]])
B = np.array([[7, 8], [9, 10], [11, 12]])
dot_product = np.dot(A, B)
print('행렬 내적 결과:\n',dot_product)
행렬 내적 결과:
[[ 58 64]
[139 154]]
A = np.array([[1, 2], [3, 4]])
transpose_mat = np.transpose(A)
print('A의 전치 행렬:\n', transpose_mat)
A의 전치 행렬:
[[1 3]
[2 4]]
csv 파일은 , 로 구분되어 있고 table은 \t(탭)으로 구분되어 있음
필드 구분 문자(Delimeter)의 차이
판다스는 다양한 포맷으로 된 파일을 DataFrame으로 로딩할 수 있는 편리한 API를 제공함
read_csv(), read_table(), read_fwf()
read_fwf는 fixed width, 즉 고정 길이 기반 컬럼 포맷을 DataFrame으로 로딩하기 위한 API
read_csv()의 인자인 sep에 구분 문자를 넣으면 된다.
예를 들어, 탭으로 구분 되어 있으면
read_csv('파일명', sep='\t')
read_csv에서 sep가 생략되면 자동으로 콤마 , 가 할당됨
read_csv(filepath_or_buffer, sep=',' ,...)
import pandas as pd
titanic_df = pd.read_csv(r'C:\Users\jnh02\파이썬 머신러닝 완벽가이드\01\titanic_train.csv')
titanic_df.head(3)
print('titanic_df 변수 타입:', type(titanic_df))
titanic_df 변수 타입: <class 'pandas.core.frame.DataFrame'>
print('DataFrame 크기:', titanic_df.shape)
DataFrame 크기: (891, 12)
# 칼럼 타입, Null 데이터 개수, 데이터 분포도 등의 메타 데이터 등 조회
# info(), describe()
titanic_df.info()
titanic_df.describe()
titanic_pclass = titanic_df['Pclass']
print(type(titanic_pclass))
<class 'pandas.core.series.Series'>
value_counts = titanic_df['Pclass'].value_counts()
print(type(value_counts))
print(value_counts)
<class 'pandas.core.series.Series'>
3 491
1 216
2 184
Name: Pclass, dtype: int64
리스트 → DataFrame
ndarray → DataFrame
딕셔너리 → DataFrame
import numpy as np
col_name1=['col1']
list1 = [1, 2, 3]
array1 = np.array(list1)
print('array1 shape:', array1.shape)
#리스트를 이용해 DataFrame 생성
df_list1 = pd.DataFrame(list1, columns=col_name1)
print('1차원 리스트로 만든 DataFrame:\n', df_list1)
#넘파이 ndarray를 이용해 DataFrame 생성
df_array1 = pd.DataFrame(array1, columns=col_name1)
print('1차원 ndarray로 만든 DataFrame:\n', df_array1)
array1 shape: (3,)
1차원 리스트로 만든 DataFrame:
col1
0 1
1 2
2 3
1차원 ndarray로 만든 DataFrame:
col1
0 1
1 2
2 3
# 3개의 칼럼명 필요
col_name2=['col1', 'col2', 'col3']
# 2행x3열 형태의 리스트와 ndarray 생성한 뒤 이를 DataFrame으로 변환
list2 = [[1,2,3], [11,12,13]]
array2 = np.array(list2)
print('array2 shape:', array2.shape)
df_list2 = pd.DataFrame(list2, columns=col_name2)
print('2차원 리스트로 만든 DataFrame:\n', df_list2)
df_array2 = pd.DataFrame(array2, columns=col_name2)
print('2차원 ndarray로 만든 DataFrame:\n', df_array2)
array2 shape: (2, 3)
2차원 리스트로 만든 DataFrame:
col1 col2 col3
0 1 2 3
1 11 12 13
2차원 ndarray로 만든 DataFrame:
col1 col2 col3
0 1 2 3
1 11 12 13
# key는 문자열 칼럼명으로 매핑, value는 리스트형(또는 ndarray) 컬럼 데이터로 매핑
dict = {'col1':[1, 11], 'col2':[2, 22], 'col3':[3, 33]}
df_dict = pd.DataFrame(dict)
print('딕셔너리로 만든 DataFrame:\n', df_dict )
딕셔너리로 만든 DataFrame:
col1 col2 col3
0 1 2 3
1 11 22 33
DataFrame → ndarray (values 이용해 쉽게 바꿀 수 있음)
DataFrame → list (tolist() 이용)
DataFrame → 딕셔너리(to_dict('list') 이용)
# DataFrame을 ndarray로 변환
array3 = df_dict.values
print('df_dict.values 타입:', type(array3), 'df_dict.values shape:', array3.shape)
print(array3)
# DataFrame을 리스트로 변환
list3 = df_dict.values.tolist()
print('df_dict.values.tolist() 타입:', type(list3))
print(list3)
# DataFrame을 딕셔너리로 변환
dict3 = df_dict.to_dict('list')
print('\n df_dict.to_dict() 타입:', type(dict3))
print(dict3)
df_dict.values 타입: <class 'numpy.ndarray'> df_dict.values shape: (2, 3)
[[ 1 2 3]
[11 22 33]]
df_dict.values.tolist() 타입: <class 'list'>
[[1, 2, 3], [11, 22, 33]]
df_dict.to_dict() 타입: <class 'dict'>
{'col1': [1, 11], 'col2': [2, 22], 'col3': [3, 33]}
DataFrame의 칼럼 데이터 세트 생성과 수정
[ ] 연산자를 이용해 데이터 세트 생성과 수정을 쉽게 할 수 있음
# Age_0 이라는 컬럼 추가하고 0이라는 값 할당
titanic_df['Age_0']=0
titanic_df.head(3)
# 기존 컬럼 가공해서 새로운 칼럼 Series 생성
titanic_df['Age_by_10'] = titanic_df['Age']*10
titanic_df['Family_No'] = titanic_df['SibSp'] + titanic_df['Parch']+1
titanic_df.head(3)
# 기존 칼럼 값 쉽게 일괄 업데이트
titanic_df['Age_by_10'] = titanic_df['Age_by_10'] + 100
titanic_df.head(3)
삭제 drop 메서드 이용
DataFrame.drop(labels=None, aixs=0, index=None, columns=None, level=None, inplace=False, errors='raise')
titanic_drop_df = titanic_df.drop('Age_0', axis=1)
titanic_drop_df.head(3)
# 원본에는 삭제되어 있지 않음.
# inplace를 false 설정을 해둬서 그럼
drop_result = titanic_df.drop(['Age_0', 'Age_by_10', 'Family_No'], axis=1, inplace=True)
print('inplcae true로 drop 후 결과:', drop_result)
titanic_df.head(3)
inplcae true로 drop 후 결과: None
# inplace true로 설정하면 반환 값은 None임
# 원본 DataFrame이 알아서 바뀌니 다시 할당하면 안됨
# 다시 할당하면 titnaic_df 객체 변수를 아예 None으로 바꿔버림
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 15)
print('#### before axis 0 drop ####')
print(titanic_df.head(3))
# 로우 인덱스로 삭제
titanic_df.drop([0,1,2], axis=0, inplace=True)
print('#### after axis 0 drop ####')
print(titanic_df.head(3))
- axis : DataFrame의 로우를 삭제할 때는 axis=0, 칼럼을 삭제할 때는 axis=1으로 설정
- 원본 DataFrame을 유지하고 드롭된 DataFrame을 새롭게 객체 변수로 받고 싶으면 inplace=False로 설정(디폴트도 False)
- 원본 DataFrame에 드롭된 결과를 적용할 경우 inplace=True 로 적용
- 원본 DataFrame에서 드롭된 DataFrame을 다시 원본 DataFrame 객체 변수로 할당하면 원본 DataFrame에서 드롭된 결과를 적용할 경우와 같음(단, 기존 원본 DataFrame 객체 변수는 메모리에서 추후 제거됨)
인덱스
- 식별성 데이터를 1차원 array로 가짐
- 단일 값 반환, 슬라이싱 가능
- 한 번 만들어진 DataFrame, Series의 Index 객체는 함부로 변경할 수 없음
- Series 객체는 Index 객체를 포함하나 Series 객체에 연산 함수를 적용할 때 Index는 연산에서 제외된다. Index는 오직 식별용으로 사용된다.
- DataFrame 및 Series에서 reset_index() 메서드 수행시 새롭게 인덱스를 연속 숫자형으로 할당하며 기존 인덱스는 'index'라는 새로운 칼럼 명으로 추가한다.
- Series에 reset_index를 적용하면 DataFrame이 반환된다. 새로운 연속 숫자형 인덱스가 만들어지고 기존 인덱스는 'index' 칼럼명으로 추가되면서 DataFrame을 반환함(Series를 반환하는 것이 아님)
- reset_index()의 파라미터 중 drop=True를 설정하면 기존 인덱스는 새로운 칼럼으로 추가되지 않고 삭제된다. 새로운 칼럼이 추가되지 않으므로 그대로 Series로 유지된다.
# 인덱스 객체 추출
indexes = titanic_df.index
print(indexes)
# index 객체를 실제 값 array로 변환
print('Index 객체 array값:\n', indexes.values)
titanic_reset_df = titanic_df.reset_index(inplace=False)
titanic_reset_df.head(3)
print('#### before reset_index ####')
value_counts = titanic_df['Pclass'].value_counts()
print(value_counts)
print('value_counts 객체 타입 변수:', type(value_counts))
new_value_counts = value_counts.reset_index(inplace=False)
print('### After reset_index ###')
print(new_value_counts)
print('new_value_counts 객체 타입 변수:', type(new_value_counts))
데이터 셀렉션 및 필터링
넘파이의 경우 [ ] 연산자를 통해 단일 값 추출, 슬라이싱, 팬시 인덱싱, 불린 인덱싱을 해서 데이터를 추출함.
판다스는 ix[], iloc[], loc[] 연산자를 통해 동일한 작업을 수행한다.
- 데이터프레임의 [ ] 연산자
- 행의 위치, 열의 위치, 슬라이싱 범위 등을 지정해 데이터를 가져올 수 있음
- [ ] 안에는 칼럼 명 문자, 인덱스로 변환 가능한 표현식
- DataFrame의 []는 넘파이의 []나 Series[] 와 다름
- 칼럼명을 지정해 칼럼 지정 연산에 사용하거나 불린 인덱스 용도로만 사용해야 한다.
- DataFrame[0:2] 같은 슬라이싱 연산으로 데이터 추출은 안하는게 좋음
print(titanic_df['Pclass'].head(3))
print(titanic_df[['Pclass', 'Survived']].head(3))
print(titanic_df['Pclass'].head(3))
titanic_df[titanic_df['Pclass']==3].head(3)
- DataFrame ix[] 연산자
- DataFrame의 인덱스값은 명칭 기반 인덱싱
- ix[]는 명칭과 위치 기반 인덱싱을 모두 허용하고
- loc[] 는 명칭 기반 인덱싱
- iloc[]는 위치 기반 인덱싱
- iloc[] 연산자
- 위치 기반 인덱싱
- 행과 열 값으로 integer 또는 integer형의 슬라이싱, 팬시 리스트 값을 입력
- 불린 인덱싱은 제공하지 않음
- loc[] 연산자
- 명칭 기반 인덱싱
- 행 위치에는 DataFrame index 값을, 열 위치에는 칼럼 명 입력
- 인덱스가 숫자 형일 수 있기 때문에 명칭 기반이라고 무조건 문자열을 입력하라는 선입견은 안됨
- 주의할 점으로 loc[] 안에서 슬라이싱을 할 경우 보통 0:3이면 3 미만으로 0 1 2지만 loc 안에서는 0 1 2 3 으로 마지막 숫자를 포함함
- 명칭 기반 인덱스라서 그럼. 명칭은 숫자형이 아닐 수 있기 때문에 -1을 적용하지 않음.
data_df.iloc[0, 0]
# 인덱싱이 아닌 명칭을 입력하면 오류 발생
# ValueError
data_df.iloc[0, 'Name']
# 문자열 인덱스를 행 위치에 입력해도 오류 발생
data_df.iloc['one', 0]
data_df_reset.iloc[0, 1]
# 명칭 기반인 loc[] 연산자
data_df.loc['one', 'Name']
data_df_reset.loc[1, 'Name']
# 인덱스값이 0인 행이 없으므로 오류 발생
data_df_reset.loc[0, 'Name']
- ix, iloc, loc의 차이
- 명칭 기반 인덱싱과 위치 기반 인덱싱의 차이를 이해할 것.
- DataFrame의 인덱스나 칼럼명으로 데이터에 접근하는게 명칭 기반, 0부터 시작하는 행, 열의 위치 좌표에만 의존하는게 위치 기반 인덱싱
- ix[]는 명칭, 위치 모두 적용할 수 있음. DataFrame의 인덱스가 숫자 형인 경우 행 위치에 오는 숫자는 위치 기반 인덱싱이 아니라 명칭 기반 인덱싱의 DataFrame 인덱스를 가리킴
- iloc[] 는 위치 기반 인덱싱만 가능함. 따라서 행과 열 위치 값으로 정수형 값을 지정해 원하는 데이터를 반환
- loc[] 는 명칭 기반 인덱싱만 가능함. 따라서 행 위치에 DataFrame 인덱스가 오며, 열 위치에는 칼럼 명을 지정해 원하는 데이터를 반환함
- 명칭 기반 인덱싱에서 슬라이싱을 '시작점:종료점'으로 지정할 때 시작점에서 종료점을 포함한 위치에 있는 데이터를 반환함
- 불린 인덱싱
titanic_boolean = titanic_df[titanic_df['Age']>60]
print(type(titanic_boolean))
titanic_boolean
titanic_df[titanic_df['Age']>60][['Name', 'Age']].head(3)
titanic_df.loc[titanic_df['Age']>60][['Name', 'Age']].head(3)
titanic_df[(titanic_df['Age']>60) & (titanic_df['Pclass']==1) & (titanic_df['Sex']=='female')]
cond1 = titanic_df['Age'] > 60
cond2 = titanic_df['Pclass']==1
cond3 = titanic_df['Sex']=='female'
titanic_df[cond1 & cond2 & cond3]
- 정렬, Aggregation 함수, GroupBy 적용
- sort_values() 메서드
- 파라미터 : by, ascending, inplac
- Aggreagation 함수
- count() → 모든 칼럼에 count() 결과 반환
- 특정 컬럼에만 적용하려면 aggregation
- groupby() 적용
- SQL의 group by 와 달리, DataFrame에 groupby()를 호출해 반환된 결과에 aggregation 함수를 호출하면 groupby() 대상 칼럼을 제외한 모든 칼럼에 해당 aggreagtion 함수를 적용함.
- sort_values() 메서드
titanic_sorted = titanic_df.sort_values(by=['Name'])
titanic_sorted.head(3)
titanic_sorted = titanic_df.sort_values(by=['Pclass', 'Name'], ascending=False)
titanic_sorted.head(3)
titanic_df.count()
titanic_df[['Age', 'Fare']].mean()
titanic_groupby = titanic_df.groupby('Pclass').count()
titanic_groupby
titanic_groupby = titanic_df.groupby('Pclass')[['PassengerId', 'Survived']].count()
titanic_groupby
titanic_df.groupby('Pclass')['Age'].agg([max, min])
agg_format={'Age':'max', 'SibSp':'sum', 'Fare':'mean'}
titanic_df.groupby('Pclass').agg(agg_format)
- 결손데이터 처리
- NaN으로 표시됨
- 기본적으로 머신러닝은 NaN 값을 처리하지 않으므로 이 값을 다른 값으로 대체해야함
- NaN은 평균, 총합 등의 함수 연산 시 제외된다.
- isna()으로 NaN 여부를 확인할 수 있고 다른 값으로 대체하려면 fillna() 사용
titanic_df.isna().head(3)
titanic_df.isna().sum()
titanic_df['Cabin'] = titanic_df['Cabin'].fillna('C000')
titanic_df.head(3)
titanic_df['Age'] = titanic_df['Age'].fillna(titanic_df['Age'].mean())
titanic_df['Embarked'] = titanic_df['Embarked'].fillna('S')
titanic_df.isna().sum()
- apply lambda 식으로 데이터 가공
- 판다스는 apply 함수에 람다 식을 결합해 데이터프레임이나 시리즈의 레코드별로 데이터를 가공하는 기능을 제공
- 판다스의 경우 속도를 위해 apply lambda를 이용함
- lambda x(입력인자) : x ** 2(입력 인자를 기반으로 한 계산식이며 호출 시 계산 결과가 반환됨)
lambda_square = lambda x : x ** 2
print('3의 제곱은:', lambda_square(3))
3의 제곱은: 9
a=[1, 2, 3]
squares = map(lambda x : x**2, a)
list(squares)
[1, 4, 9]
titanic_df['Name_len'] = titanic_df['Name'].apply(lambda x : len(x))
titanic_df[['Name', 'Name_len']].head(3)
titanic_df['Child_Adult'] = titanic_df['Age'].apply(lambda x : 'Child' if x <=15 else 'Adult')
titanic_df[['Age', 'Child_Adult']].head(8)
titanic_df['Age_cat'] = titanic_df['Age'].apply(lambda x : 'Child' if x <=15 else ('Adult' if x <= 60 else 'Elderly'))
titanic_df['Age_cat'].value_counts()
# 나이에 따라 세분화된 분류 수행하는 함수
def get_category(age):
cat = ''
if age <= 5: cat = 'Baby'
elif age <= 12: cat = 'Child'
elif age <= 18: cat = 'Teenager'
elif age <= 25: cat = 'Student'
elif age <= 35: cat = 'Young Adult'
elif age <= 60: cat = 'Adult'
else : cat = 'Elderly'
return cat
# lambda 식에 위에서 생성한 get_category() 함수를 반환값으로 지정
# get_category(x)는 입력값으로 'Age' 칼럼 값을 받아서 해당하는 cat 반환
titanic_df['Age_cat'] = titanic_df['Age'].apply(lambda x : get_category(x))
titanic_df[['Age', 'Age_cat']].head()
'머신러닝' 카테고리의 다른 글
[파이썬 머신러닝 완벽가이드] CH03 (0) | 2021.09.26 |
---|---|
[파이썬 머신러닝 완벽가이드] CH02 (0) | 2021.09.26 |