2021. 1. 29. 22:14ㆍ교육과정/KOSMO
키워드 : 파이썬 넘파이 ( Numpy ) / 파이썬 판다스 ( Pandas ) / 파이썬 맷플랏 ( matplot ) 시각화 /
****
numpy¶
-
행렬 / 선형대수 / 통계 패키지
-
머신러닝의 이론적 백그라운드는 선형대수와 통계로 이루어져 있다
-
사이킷런 같은 머신러닝 패키지가 넘파이 기반으로 되어 있다
* 머신러닝 알고리즘이나 사이파이와 같은 과학, 통계 지원용 패키지를 직접 만드는 개발이 아니라면
넘파이를 상세하기 알 필요는 없다지만, 넘파이를 이해하는 것이 파이썬 기반의 데이타분석과 머신러닝에 중요하다
* 넘파이가 데이타 핸들링에 효율적으로 쉽고 편하고 할 수 없다.
그러나 데이타 핸들링에 주로 사용하는 판다스도 많은 부분이 넘파이를 기반으로 만들어져 있다.
* ndarray
- 넘파이 기반 데이타 타입
- np.array()
- Numpy 라이브러리는 일반적으로 np 라는 별칭으로 import 한다.¶
import numpy as np
list_1 = [1,2,3]
list_2 = [9,8,7]
arr = np.array([list_1, list_2])
arr
array([[1, 2, 3],
[9, 8, 7]])
- arr의 상세한 설명을 보려면 물음표로 출력한다.
arr?
- 파이썬과 Numpy의 list는 type 이 다르다.
print(type(list_1)) # 파이썬의 list
print(type(arr)) # Numpy의 dnarray
<class 'list'>
<class 'numpy.ndarray'>
- 리스트의 형태를 확인하여 파이썬 자료형인지 Numpy 자료형인지 확인할 수 있다.
arr.shape
(2, 3)
- Q. 두 번째 행에 두 번째 열의 요소를 100 으로 변경하고 출력하기
arr
array([[1, 2, 3],
[9, 8, 7]])
arr[1,1] = 100
arr
array([[ 1, 2, 3],
[ 9, 100, 7]])
- Q. 두 변수 arr1, arr2 의 타입과 형태를 출력하기
arr1 = np.array([1,2,3])
arr2 = np.array([[1,2,3]])
print(arr1.shape) # 요소가 3개 들어있음을 튜플 형태로 출력해줌
print(arr2.shape) # 2차원 배열이 들어있음을 튜플 형태로 출력해줌 -- 1행 3열
(3,)
(1, 3)
- 차원수로 출력하기
print(arr1.ndim)
print(arr2.ndim)
1
2
자료형¶
print(type(arr)) # arr의 자료형 확인
print(arr.dtype) # arr에 들어있는 데이터의 자료형 확인
<class 'numpy.ndarray'>
int32
- 데이터의 타입을 변경하기 --- astype( )
arr2 = arr.astype(np.float64)
print(arr2.dtype)
arr2
float64
array([[ 1., 2., 3.],
[ 9., 100., 7.]])
- 데이터의 타입을 int32로 변경 후 출력하기
arr = [1.1, 2.2, 3.3]
arr3 = np.array(arr, dtype='int32')
print(arr3.dtype)
arr3
int32
array([1, 2, 3])
- 데이터의 타입 확인하기 (기본형 --- float64)
list = [9, 2.2]
arr = np.array(list)
print(arr.dtype)
float64
- 다양한 타입의 데이터가 들어있을 경우, 가장 큰 데이터 타입으로 나머지도 인식한다.
list = [9, 2.2]
arr = np.array(list)
print(type(arr))
print(arr.dtype)
<class 'numpy.ndarray'>
float64
list = [9, 2.2, 'python']
arr = np.array(list)
print(type(arr))
print(arr.dtype)
<class 'numpy.ndarray'>
<U32
a = np.arange(10)
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b = np.arange(10,20)
b
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
c = np.arange(100,120,3)
c
array([100, 103, 106, 109, 112, 115, 118])
- d = np.zeros(5,5) 은 shape 을 int 또는 tuple 로 지정
d = np.zeros((5,5))
d
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
- 3행 3열의 정수 1로 채워진 행렬
e = np.ones((3,3))
e
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
ndarray의 차원과 크기를 변경 : reshape()¶
arr = np.arange(20)
print(arr)
print(arr.shape)
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
(20,)
- 차원과 크기 변경 -- 갯수가 맞아야 한다.
arr1 = arr.reshape(4,5)
print(arr1)
print(arr1.shape)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
(4, 5)
arr2 = arr.reshape(2,2,5)
print(arr2)
print(arr2.shape)
[[[ 0 1 2 3 4]
[ 5 6 7 8 9]]
[[10 11 12 13 14]
[15 16 17 18 19]]]
(2, 2, 5)
-1을 사용하면 알아서 행 또는 열을 맞춰서 재배열해준다.¶
arr3 = arr.reshape(5,-1)
print(arr3)
print(arr3.shape)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]]
(5, 4)
arr4 = arr.reshape(-1,5)
print(arr4)
print(arr4.shape)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
(4, 5)
인덱싱: 특정 데이타 추출¶
#------------------------------------------ (1) 단일값 출력
import numpy as np
arr = np.arange(1, 11)
print(arr)
[ 1 2 3 4 5 6 7 8 9 10]
- 세번째 요소 추출 ( 0부터 인덱스)
arr[2]
3
- 뒤에서 세번째 요소 추출 ( 뒤에서 인덱스는 -1부터)
arr[-3]
8
- 1부터 9까지 nparray를 만들고 3행 3열 2차원 구조로 변경한후
- 두번째 행의 세번째 열의 값 추출하기
ilgu = np.arange(1,10)
ilgu
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
ilgu2 = ilgu.reshape(3,3)
ilgu2
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(ilgu2[1,2])
6
슬라이싱¶
arr = np.arange(1, 10)
arr
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(arr[5:])
[6 7 8 9]
arr = np.arange(1,10)
arr2 = arr.reshape(3,3)
arr2
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
Q. 행렬에서 1, 2, 4, 5 추출
print(arr2[:2, :2])
[[1 2]
[4 5]]
Q. 행렬에서 4, 5, 6, 7, 8, 9 추출
print(arr2[1:])
[[4 5 6]
[7 8 9]]
print(arr2[1:3, 0:3])
[[4 5 6]
[7 8 9]]
Q. 행렬에서 2, 3, 5, 6 추출
print(arr2[0:2, 1:4])
[[2 3]
[5 6]]
Q. 행렬에서 1, 4 추출
print(arr2[0:2, 0:1])
[[1]
[4]]
불린 인덱싱¶
- 조건 필터링과 검색을 같이 하기에 자주 사용한다.
arr = np.arange(1, 10)
ndarr = arr.reshape(3,3)
print(ndarr)
[[1 2 3]
[4 5 6]
[7 8 9]]
Q. 5보다 큰 요소들 추출
barr = (ndarr > 5 )
barr
array([[False, False, False],
[False, False, True],
[ True, True, True]])
ndarr[barr]
array([6, 7, 8, 9])
Q. 8값 요소를 88로 변경
over8 = (ndarr == 8)
over8
array([[False, False, False],
[False, False, False],
[False, True, False]])
ndarr[over8] = 88
ndarr
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 88, 9]])
numpy 연산¶
- abx / fabs : 절대값
- sqrt : 제곱근
- square : 제곱
- exp : 지수
- ceil / floor : 소수자릿수 올림/내림
- rint :소수자릿수 반올림
- modf : 원소의 몫과 나머지를 각 배열로 변환
-
lsnan : 각 원소가 Nan인지 아닌지 불린 배열로 리턴
-
add / subtract : 두 배열의 같은 위치의 요소끼리 덧셈/뺄셈
- multiply : 배열 원소끼리 곱셉
- divide : 첫번째 배열의 원소에서 두번째 배열 원소로 나눔
- power : 첫번째 배열의 원소에 두번째 배열의 원소만큼 제곱
- maximum : 비교하는 두 원소 중 큰 값
- mod : 첫번째 배열의 원소에서 두번째 배열 원소로 나눈 나머지
import numpy as np
arr1 = np.array([[1,2,3],[4,5,6]])
arr2 = np.array([[1,1,1],[2,2,2]])
arr1
array([[1, 2, 3],
[4, 5, 6]])
arr2
array([[1, 1, 1],
[2, 2, 2]])
배열의 연산은 각 요소를 가지고 이루어진다.
print(arr1 + arr2)
[[2 3 4]
[6 7 8]]
print(arr1 - arr2)
[[0 1 2]
[2 3 4]]
print(arr1 * arr2) # 요소의 곱 (o) 행렬의 곱 (x)
[[ 1 2 3]
[ 8 10 12]]
(2) 행렬의 곱¶
A = np.array(
[[1, 2, 3],
[4, 5, 6]])
B = np.array(
[[7,8],
[9,10],
[11, 12]])
(17 + 29 + 3*11) = 58
print(np.dot(A,B))
[[ 58 64]
[139 154]]
(3) 전치행렬¶
- 원 행렬에서 행과 열 위치를 교환한 원소로 구성한 행렬
A = np.array(
[[1, 2, 3],
[4, 5, 6]])
print(np.transpose(A))
[[1 4]
[2 5]
[3 6]]
넘파이 통계 함수¶
- sum : 배열 원소들의 합
- mean :산술 평균
- std / var : 표준편차 / 분산
- min / max : 최소 값 / 최대 값
- cumsum : 각 원소의 누적값
- cumprod : 각 원소의 누적곱
import numpy as np
ar = np.array([1,3,5,7])
평균
np.mean(ar)
4.0
총합
np.sum(ar)
16
최댓값
np.max(ar)
7
2차원 배열에서¶
arr = np.array([[1,2,3],[4,5,6]])
arr
array([[1, 2, 3],
[4, 5, 6]])
총합
np.sum(arr)
21
특정 행의 합
np.sum(arr[1])
15
axis=0 : 행방향 - 열단위 합
np.sum(arr, axis=0)
array([5, 7, 9])
axis=1 : 열방향 - 행단위 합
np.sum(arr, axis=1)
array([ 6, 15])
불린 배열에서의 배열
조건에 의한 T, F 에 따라 출력해준다.
arr2 = np.array([[12, 7, 22], [20,33, 44], [4,5,6]])
arr2
array([[12, 7, 22],
[20, 33, 44],
[ 4, 5, 6]])
arr2[ arr2 > 20 ]
array([22, 33, 44])
print( (arr2 > 20).sum() ) # True 가 3개이고, True=1 이므로 1+1+1 의 결과가 출력된다.
3
print( arr2 [ arr2 > 20].sum() )
99
unique 연산자를 이용하여 중복제거
region = np.array(['가산','서울','서울','판교','가산'])
region
array(['가산', '서울', '서울', '판교', '가산'], dtype='<U2')
np.unique(region)
array(['가산', '서울', '판교'], dtype='<U2')
행렬의 정렬¶
arr = np.array([9,3,6,1,7,2,4,8,5,6])
arr
array([9, 3, 6, 1, 7, 2, 4, 8, 5, 6])
np.sort(arr)
array([1, 2, 3, 4, 5, 6, 6, 7, 8, 9])
- 역순 정렬
np.sort(arr)[::-1]
array([9, 8, 7, 6, 6, 5, 4, 3, 2, 1])
arr2 = np.array([[9,3,6],[1,7,2],[4,8,5]])
arr2
array([[9, 3, 6],
[1, 7, 2],
[4, 8, 5]])
print(np.sort(arr2, axis=None))
[1 2 3 4 5 6 7 8 9]
print(np.sort(arr2, axis=0))
[[1 3 2]
[4 7 5]
[9 8 6]]
print(np.sort(arr2, axis=1))
[[3 6 9]
[1 2 7]
[4 5 8]]
dd
난수 발생¶
-
파이썬 내장 random 모듈보다 더 빠르게 많은 난수 표본 데이타를 생성
-
적합한 난수는 시뮬레이션의 결과에 영향을 미치기에 중요함
[ ex ] 시뮬레이션의 난수 발생
침대 매트릭스의 충격완화 시뮬레이션을 한다고 할 때 1번 실험에 공을 50번을 던진다면 힘의 세기를 0~1 단위라고 할 때 임의의 힘의 세기로 50번 던졌을 때 평균 강도를 구할 수 있는데, 이 때 임의의 수 난수 발생을 numpy를 이용한다. 그러나 기본 패키지의 random 함수를 이용하지 않고 numpy을 이용하는 이유는 numpy가 속도도 빠르고 더 세밀하게 난수를 발생시킨다.
numpy의 난수 발생 함수의 차이를 조사하세요¶
1) np.random.random([n, m])
2) np.random.normal(size=( n, m))
3) np.random.randn(n,m)
4) np.random.rand(n,m)
5) np.random.randint(n, m)
import numpy as np
import matplotlib.pyplot as plt
맵플롯으로 시각화 할 수 있다.
arr = np.random.rand(100)
arr
array([0.05434952, 0.15558374, 0.27447013, 0.35233264, 0.86877817,
0.53452307, 0.75503977, 0.44630056, 0.46584151, 0.73266815,
0.67153237, 0.8604999 , 0.98131197, 0.10829237, 0.34122445,
0.12732455, 0.79374239, 0.85053125, 0.23942726, 0.56242733,
0.83981072, 0.68357496, 0.4227528 , 0.06454714, 0.00647637,
0.83424726, 0.81057144, 0.30768389, 0.46537199, 0.51678115,
0.12449577, 0.7535287 , 0.72073141, 0.86056983, 0.95267233,
0.79167509, 0.26073073, 0.52243551, 0.01968959, 0.42579744,
0.92627647, 0.56192733, 0.23381096, 0.66134504, 0.63528734,
0.65818783, 0.3306125 , 0.91892571, 0.40800526, 0.85438845,
0.86192193, 0.99089237, 0.78781168, 0.35721432, 0.7085522 ,
0.67252292, 0.15646733, 0.21185563, 0.61776441, 0.19577937,
0.55329127, 0.18371867, 0.63537922, 0.94339331, 0.93809225,
0.80991923, 0.40412705, 0.51728178, 0.48899887, 0.76819403,
0.19283098, 0.25741633, 0.18443425, 0.04829806, 0.76750562,
0.19659657, 0.39865536, 0.66101515, 0.27682676, 0.41923101,
0.85645631, 0.32361188, 0.88530836, 0.89577721, 0.46663495,
0.1117159 , 0.15056815, 0.9826056 , 0.91765957, 0.09827534,
0.21884415, 0.06935177, 0.19301622, 0.99669445, 0.4301137 ,
0.72520559, 0.58643129, 0.9467847 , 0.83041168, 0.28928431])
%는 주피터노트북의 매직키워드
%matplotlib inline
plt.plot(arr);
arr1 = np.random.random([2, 3]) # 0~1 사이에 난수 추출
arr1
array([[0.78355211, 0.58219332, 0.89334617],
[0.42268395, 0.0181514 , 0.50163239]])
arr2 = np.random.normal(size=(2,3))
arr2
array([[-0.77648438, 0.68802819, -0.92792595],
[-0.79365234, 0.64141689, -0.95485271]])
arr3 = np.random.randn(2,3)
arr3
array([[ 1.36465941, -0.05174408, -0.48452959],
[-0.17479391, -1.1831528 , -0.66156909]])
arr4 = np.random.rand(2,3)
arr4
array([[0.77928971, 0.024979 , 0.84929181],
[0.56101142, 0.41557176, 0.74315004]])
arr5 = np.random.randint(2,3)
arr5
2
[참고]¶
-
random : 0.0에서 1.0 사이의 난수 추출
-
rand : 균등분포에서 표준 추출
-
randint : 최소, 최대 범위내에서 임의의 난수 추출
-
randn : 표준편차 1, 평균값 0인 정규분포에서 표준 추출
-
normal : 정규분포에서 표준추출
-
shuffle : 리스트나 배열의 순서를 뒤섞음
[참고]¶
NumPy의 random 서브패키지에는 난수를 생성하는 다양한 명령을 제공한다. 그 중 가장 간단하고 많이 사용되는 것은 다음 3가지 명령이다.
• rand: 0부터 1사이의 균일 분포
• randn: 가우시안 표준 정규 분포
• randint: 균일 분포의 정수 난수
rand 명령은 0부터 1사이에서 균일한 확률 분포로 실수 난수를 생성한다. 숫자 인수는 생성할 난수의 크기이다. 여러개의 인수를 넣으면 해당 크기를 가진 행렬을 생성한다.
[참고] 데이타 사이언스 스쿨¶
파이썬 > 난수 발생과 카운팅
https://datascienceschool.net/view-notebook/8bf41f87a08b4c44b307799577736a28/
import numpy as np
origin = np.array([3,1,9,7])
print('원본:', origin)
원본: [3 1 9 7]
넘파이 sort
result = np.sort(origin)
print('원본:', origin)
print('결과:', result)
원본: [3 1 9 7]
결과: [1 3 7 9]
행렬의 sort
result = origin.sort()
print('원본:', origin)
print('결과:', result)
원본: [1 3 7 9]
결과: None
내림차순 정렬 [::-1]¶
origin = np.array([3,1,9,7])
print('원본:', origin)
원본: [3 1 9 7]
넘파이 sort 후 내림차순 정렬
result = np.sort(origin)
print('결과:', result)
print('정렬:', result[::-1])
결과: [1 3 7 9]
정렬: [9 7 3 1]
행렬의 sort 후 내림차순 정렬
origin.sort()
print('원본', origin)
print('정렬:', origin[::-1])
원본 [1 3 7 9]
정렬: [9 7 3 1]
2차원 이상의 행렬에서¶
- axis=0 : 행방향 -> 열단위
- axis=1 : 열방향 -> 행단위
arr = np.array([[9, 6, 3],[5, 11, 2]])
arr
array([[ 9, 6, 3],
[ 5, 11, 2]])
?np.sort
'행방향 -> 열단위'
print(np.sort(arr, axis=0))
[[ 5 6 2]
[ 9 11 3]]
'열방향 -> 행단위'
print(np.sort(arr, axis=1))
[[ 3 6 9]
[ 2 5 11]]
번외
print(np.sort(arr, axis=None))
[ 2 3 5 6 9 11]
정렬된 행렬의 인덱스 반환 : argsort()¶
arr = np.array([3, 8, 2, 5])
arr
array([3, 8, 2, 5])
오름차순으로 정렬된 행렬의 인덱스를 반환한다.
오름차순으로 정렬한 행렬 : [2, 3, 5, 8]
np.argsort(arr)
array([2, 0, 3, 1], dtype=int64)
2의 위치 : 2번째
3의 위치 : 0번째
5의 위치 : 3번째
8의 위치 : 1번째
예제) 점수에 따라 이름을 정렬하고자 할 때 사용할 수 있다.
score = np.array([66,99,55,88,77])
names = np.array(['홍', '김', '박', '최', '이'])
idx = np.argsort(score)
print(idx)
[2 0 4 3 1]
for i in idx:
print(names[i], '-', score[i])
박 - 55
홍 - 66
이 - 77
최 - 88
김 - 99
Series¶
-
DataFrame의 한 컬럼 데이터 세트
-
Series 역시 DataFrame의 인덱스와 동일한 인덱스를 가진다
-
즉 Series는 컬럼이 하나인 데이타 구조체이고, DataFrame은 컬럼이 여러개인 데이타 구조체이다
DataFrame을 RDBMS의 테이블과 유사하다면, Series는 테이블의 한 컬럼과 유사다하고 볼 수 있다
# from pandas import Series
# age_in = Series([22,33,44,25,28])
import pandas as pd
age_in = pd.Series([22,33,44,25,28])
age_in
0 22
1 33
2 44
3 25
4 28
dtype: int64
Q. Series의 index를 출력 (추상화된 불변의 index)
age_in.index
RangeIndex(start=0, stop=5, step=1)
Q. Series의 값을 출력
age_in.values
array([22, 33, 44, 25, 28], dtype=int64)
Q. Series의 key를 출력
age_in.keys
<bound method Series.keys of 0 22
1 33
2 44
3 25
4 28
dtype: int64>
keys와 keys()는 다른 결과가 출력된다.
age_in.keys()
RangeIndex(start=0, stop=5, step=1)
인덱스 지정하며 시리즈 생성
age_in = pd.Series( [22,33,44,25,28], index=['가', '나', '다', '라', '마'] )
age_in
가 22
나 33
다 44
라 25
마 28
dtype: int64
Q. '다' 요소에 100 지정
age_in['다'] = 100
age_in
가 22
나 33
다 100
라 25
마 28
dtype: int64
Series 인덱스 중복 확인
srs = pd.Series( ['가', '나', '다'], index=['a', 'b', 'a'])
srs
a 가
b 나
a 다
dtype: object
→ Series의 index는 key처럼 사용되지만 중복이 가능하다.
Q. index가 a 인 Series 출력
print(srs['a'])
a 가
a 다
dtype: object
Q. index가 b인 Series 출력
print(srs['b'])
나
Q. 값이 '가' 인 것만 출력
print(srs[0])
가
딕셔너리를 시리즈 형태로 변환
- 딕셔너리는 python의 자료형
- 시리즈는 pandas의 자료형
info_list = { 'kim': 25, 'park':22, 'lee':34 }
info_list
{'kim': 25, 'park': 22, 'lee': 34}
Q. 딕셔러리를 시리즈 형태로 변환
info_series = pd.Series(info_list)
info_series
kim 25
park 22
lee 34
dtype: int64
info_list = { 'kim': 25, 'park':22, 'lee':34 }
info_series = pd.Series(info_list)
info_series
kim 25
park 22
lee 34
dtype: int64
- 시리즈 형태로 변환할 때 index를 별도로 지정할 경우 기존 key를 오버라이딩 하는데,
- 새로운 index에는 value를 지정해준 바가 없어서 Nan이 출력된다.
info_list = { 'kim': 25, 'park':22, 'lee':34 }
info_series = pd.Series(info_list, index=[0, 1, 2])
info_series
0 NaN
1 NaN
2 NaN
dtype: float64
- value가 있는 index로 지정할 경우에는 값이 출력된다.
info_list = { 'kim': 25, 'park':22, '0':34 }
info_series = pd.Series(info_list, index=[0, 'park', 2])
info_series
0 NaN
park 22.0
2 NaN
dtype: float64
Q. 가,나,다 요소에 A, B, C 인덱스를 가진 시리즈 생성
## 가,나,다 요소에 A, B, C 인덱스를 가진 시리즈 생성
abc = pd.Series(['가', '나', '다'], index=['A', 'B', 'C'])
abc
A 가
B 나
C 다
dtype: object
판다스를 사용하는 이유¶
만일 파이썬의 리스트와 판다스의 Series가 거의 유사하다면, 우리는 왜 파이썬의 리스트가 아닌 판다스의 Series를 사용할까?
파이썬의 리스트를 사용하면 판다스에서 제공하는 다양한 기능을 사용할 수 없기 때문이다.
판다스 (Pandas)¶
- 핵심객체는 DataFrame이다
- 데이타프레임은 2차원 데이터 구조체로 넘파이보다 편리하게 데이타 핸들링한다.
- R 언어의 데이타 프레임과 비슷하고 많이 사용된다
DataFrame 에서 데이타 필터링 ( 추출하기 )¶
-
맨처음에는
- df[2] : 2행의 데이타 추출 → 사라짐!!
-
df['A'] : A열(컬럼) 데이타 추출
-
df[n:m] : n번째부터 m-1번째까지의 행 추출
행과 열을 섞어서 추출함.
판다스를 만든 사람이 쓴 책의 번역서를 보면 이 부분을 후회한다고 나옴
-
열(컬럼) 추출
- df.컬럼명
- df['컬럼명']
-
행 추출
- df.loc[] : 인덱스를 지정하지 않으면 인덱스(순서), 인덱스를 지정하면 인덱스명으로 추출
- df.iloc[] : 인덱스(순서)로 추출
-
df.ix[] : 명칭 기반 인덱싱과 위치 기반 인덱싱 모두 사용 (* 그러나 곧 사라질 예정 )
[참고]
-
위 3 연산자는 노련한 개발자들도 혼동하기에, 일반적으로 하나만 선택해서 사용하는 것을 권장한단다
- 넘파이와 유사한 부분으로 더우 혼동하기 쉽다
- 판다스의 DataFrame와 Series에서도 다른이 있어서 주의해야 한다
-
행과 열에서 추출
- df.loc[2, 3] : 2 행의 3열 데이타
- df.loc[1:3, 2:4] : 1부터 3행전까지의 행에서 2부터 4전까지의 열의 데이타
import pandas as pd
# 데이타 프레임 자료 생성
mydata = {
'name':['홍길동','박길동','김길동'],
'age':[22,33,44],
'dept':['컴공','국어','산업']
}
print(type(mydata))
mydata
<class 'dict'>
{'name': ['홍길동', '박길동', '김길동'],
'age': [22, 33, 44],
'dept': ['컴공', '국어', '산업']}
판다스의 자료형으로 변환
df = pd.DataFrame(mydata)
print(type(df))
df
<class 'pandas.core.frame.DataFrame'>
name | age | dept | |
---|---|---|---|
0 | 홍길동 | 22 | 컴공 |
1 | 박길동 | 33 | 국어 |
2 | 김길동 | 44 | 산업 |
Q. 열(컬럼) 추출
df.name
0 홍길동
1 박길동
2 김길동
Name: name, dtype: object
df['name']
0 홍길동
1 박길동
2 김길동
Name: name, dtype: object
Q. 행(레코드) 추출
df.loc[0]
name 홍길동
age 22
dept 컴공
Name: 0, dtype: object
df.iloc[0]
name 홍길동
age 22
dept 컴공
Name: 0, dtype: object
loc[ ] 과 iloc[ ] 의 차이
df2 = pd.DataFrame(mydata, index=['일', '이', '삼'])
df2
name | age | dept | |
---|---|---|---|
일 | 홍길동 | 22 | 컴공 |
이 | 박길동 | 33 | 국어 |
삼 | 김길동 | 44 | 산업 |
# df2.iloc['이'] 는 에러 발생! 명칭으로 추출할 수 없다.
df2.loc['이']
name 박길동
age 33
dept 국어
Name: 이, dtype: object
컬럼 추가
df
name | age | dept | |
---|---|---|---|
0 | 홍길동 | 22 | 컴공 |
1 | 박길동 | 33 | 국어 |
2 | 김길동 | 44 | 산업 |
df['gender'] = ['여자', '남자','여자']
df
name | age | dept | gender | |
---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 |
1 | 박길동 | 33 | 국어 | 남자 |
2 | 김길동 | 44 | 산업 | 여자 |
# 또 다른 방법
df[3, 'dept'] = '사회'
df
name | age | dept | gender | age+10 | (3, dept) | |
---|---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 | 사회 |
9 | 최길동 | 55 | 기계 | 남자 | 65 | 사회 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 | 사회 |
2 | 김길동 | 44 | 산업 | 여자 | 54 | 사회 |
행 추가
df.loc[9] = ['최길동', 55, '기계', '남자']
df
name | age | dept | gender | |
---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 |
1 | 박길동 | 33 | 국어 | 남자 |
2 | 김길동 | 44 | 산업 | 여자 |
9 | 최길동 | 55 | 기계 | 남자 |
변경¶
- 인덱스순서를 변경하려면 -> 인덱스는 우선 DataFrame이 있는 상태에서 변경해야 한다
df
name | age | dept | gender | |
---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 |
1 | 박길동 | 33 | 국어 | 남자 |
2 | 김길동 | 44 | 산업 | 여자 |
9 | 최길동 | 55 | 기계 | 남자 |
df2 = df.reindex( index=[2,9,0,1,3])
df2
name | age | dept | gender | |
---|---|---|---|---|
2 | 김길동 | 44.0 | 산업 | 여자 |
9 | 최길동 | 55.0 | 기계 | 남자 |
0 | 홍길동 | 22.0 | 컴공 | 여자 |
1 | 박길동 | 33.0 | 국어 | 남자 |
3 | NaN | NaN | NaN | NaN |
존재하지 않는 인덱스를 넣었을 경우에는 값이 들어가지 않는다.
- 컬럼연산
df
name | age | dept | gender | |
---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 |
1 | 박길동 | 33 | 국어 | 남자 |
2 | 김길동 | 44 | 산업 | 여자 |
9 | 최길동 | 55 | 기계 | 남자 |
연산 결과는 출력하지만 df 에 반영되지는 않는다.
df['age']+10
0 32
1 43
2 54
9 65
Name: age, dtype: int64
df
name | age | dept | gender | |
---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 |
1 | 박길동 | 33 | 국어 | 남자 |
2 | 김길동 | 44 | 산업 | 여자 |
9 | 최길동 | 55 | 기계 | 남자 |
age+10은 존재하지 않는 컬럼이므로 이 경우엔 새 컬럼이 생성된다.
df['age+10'] = df['age']+10
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 박길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
Q. 3 행에 'dept'열의 값을 '인문'으로 변경
df.loc[2, 'dept'] = '인문'
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 박길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 인문 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
컬럼명 추출
df.columns.values[2]
'dept'
Q. 3 행에 'dept'열의 값을 '건축'으로 변경
df.iloc[2,2] = '건축'
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 박길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 건축 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
Q. 3 행에 'dept'열의 값을 '산업'으로 변경
df.dept.iloc[2] = '산업'
df
C:\Users\kosmo_03\anaconda3\lib\site-packages\pandas\core\indexing.py:670: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
iloc._setitem_with_indexer(indexer, value)
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 박길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
컬럼 속성 추출¶
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 박길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
Q. 컬럼 속성 추출
df.name
0 홍길동
1 박길동
2 김길동
9 최길동
Name: name, dtype: object
df['name']
0 홍길동
1 박길동
2 김길동
9 최길동
Name: name, dtype: object
Q. 특정 컬럼의 특정행 추출 -> 즉 특정셀 추출 (2번 인덱스의 dept 컬럼값은? ) [결과] 산업
df.dept[2]
df.loc[2, 'dept']
'산업'
Q. 30세 이상의 레코드 겁색
df[df.age >= 30]
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
1 | 박길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
Q. 인덱스 1의 name 값을 '맹길동'로 변경하려면?
df.loc[1, 'name'] = '맹길동'
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
df.name[1] = '맹길동'
df
<ipython-input-29-8fb31cb2f0f8>:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
df.name[1] = '맹길동'
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
데이타 필터링¶
-
넘파이와 유사한 부분으로 더우 혼동하기 쉽다
-
판다스의 DataFrame와 Series에서도 다른 부분이 있어서 주의해야 한다
-
loc[] : 인덱스와 명칭으로 추출
-
iloc[] : 인덱스로 추출
-
ix[] : 명치 기반 인덱싱과 위치 기반 인덱싱 모두 사용 (* 그러나 곧 사라질 예정 )
위 3 연산자는 노련한 개발자들도 혼동하기에, 일반적으로 하나만 선택해서 사용하는 것을 권장한단다
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
print(df)
name age dept gender age+10
0 홍길동 22 컴공 여자 32
1 맹길동 33 국어 남자 43
2 김길동 44 산업 여자 54
9 최길동 55 기계 남자 65
print(type(df))
<class 'pandas.core.frame.DataFrame'>
print(df.loc[1])
name 맹길동
age 33
dept 국어
gender 남자
age+10 43
Name: 1, dtype: object
print(type(df.loc[1]))
<class 'pandas.core.series.Series'>
명칭기반 인덱스 : 문자열이 인덱스인 경우
# 특정 컬럼으로 인덱스를 지정
정렬과 T¶
- sort_values() : 해당 컬럼의 값으로 정렬하지만 원본은 그대로 유지
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
Q. 나이를 오름차순으로
df.sort_index(ascending=1) # 인덱스 정렬 기본값이 ascending=1
df.sort_values('name')
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
2 | 김길동 | 44 | 산업 | 여자 | 54 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
Q. 나이를 내림차순으로
df.sort_index(ascending=0) 또는 df.sort_index(ascending=False)
df.sort_values('name', ascending=False)
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
- 전문가들은 원본이 변경하지 않는 것을 권장
df_sorted = df.sort_values('name', ascending=False)
df_sorted
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
inplace=True 옵션을 줄 경우 원본이 바뀌므로 주의!
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
df.sort_values('name', ascending=False, inplace=True)
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
T 는 행과 열을 바꾼다.¶
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
df.T
0 | 9 | 1 | 2 | |
---|---|---|---|---|
name | 홍길동 | 최길동 | 맹길동 | 김길동 |
age | 22 | 55 | 33 | 44 |
dept | 컴공 | 기계 | 국어 | 산업 |
gender | 여자 | 남자 | 남자 | 여자 |
age+10 | 32 | 65 | 43 | 54 |
정보확인¶
df
name | age | dept | gender | age+10 | |
---|---|---|---|---|---|
0 | 홍길동 | 22 | 컴공 | 여자 | 32 |
9 | 최길동 | 55 | 기계 | 남자 | 65 |
1 | 맹길동 | 33 | 국어 | 남자 | 43 |
2 | 김길동 | 44 | 산업 | 여자 | 54 |
Q. 총 데이터 건수와 데이타 타입등 정보 확인
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 4 entries, 0 to 2
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 name 4 non-null object
1 age 4 non-null int64
2 dept 4 non-null object
3 gender 4 non-null object
4 age+10 4 non-null int64
dtypes: int64(2), object(3)
memory usage: 352.0+ bytes
Q. 기본통계량 구하기 ( 총개수, 평균, 표준편차, 최소값, 4분위수 등)
df.describe() 는 데이터가 숫자인 경우 모든 기본통계량 출력해준다.
df.describe()
age | age+10 | |
---|---|---|
count | 4.000000 | 4.000000 |
mean | 38.500000 | 48.500000 |
std | 14.200939 | 14.200939 |
min | 22.000000 | 32.000000 |
25% | 30.250000 | 40.250000 |
50% | 38.500000 | 48.500000 |
75% | 46.750000 | 56.750000 |
max | 55.000000 | 65.000000 |
미국 대통령 신장(키) 데이타를 분석¶
` 전체적인 기본 통계량
` 평균신장
` 그래프로 시각화
import pandas as pd
data = pd.read_csv('./data/president_heights.csv')
type(data)
pandas.core.frame.DataFrame
data.head(5)
order | name | height(cm) | |
---|---|---|---|
0 | 1 | George Washington | 189 |
1 | 2 | John Adams | 170 |
2 | 3 | Thomas Jefferson | 189 |
3 | 4 | James Madison | 163 |
4 | 5 | James Monroe | 183 |
data.tail(3)
order | name | height(cm) | |
---|---|---|---|
39 | 42 | Bill Clinton | 188 |
40 | 43 | George W. Bush | 182 |
41 | 44 | Barack Obama | 185 |
Q. 기본정보 - 자료형 확인
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 42 entries, 0 to 41
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 order 42 non-null int64
1 name 42 non-null object
2 height(cm) 42 non-null int64
dtypes: int64(2), object(1)
memory usage: 1.1+ KB
Q. 기술 통계량을 확인
data.describe()
order | height(cm) | |
---|---|---|
count | 42.000000 | 42.000000 |
mean | 22.476190 | 179.738095 |
std | 13.152461 | 7.015869 |
min | 1.000000 | 163.000000 |
25% | 11.250000 | 174.250000 |
50% | 22.000000 | 182.000000 |
75% | 33.750000 | 183.000000 |
max | 44.000000 | 193.000000 |
Q. 평균 신장을 출력
- 컬럼명에 특수문자가 있을 경우에는 [ ] 안에 넣는 방법만 사용할 수 있다.
data['height(cm)'].mean()
179.73809523809524
data.order.mean()
22.476190476190474
- 컬럼명 변경
data.head(2)
order | name | height(cm) | |
---|---|---|---|
0 | 1 | George Washington | 189 |
1 | 2 | John Adams | 170 |
data.columns = ['order', 'name', 'height']
data.head(2)
order | name | height | |
---|---|---|---|
0 | 1 | George Washington | 189 |
1 | 2 | John Adams | 170 |
- 컬럼명 그대로 중간에 넣어서 산술평균을 출력할 수 잇다.
data.height.mean()
179.73809523809524
- 시각화
print(type(data['height'].plot()))
data['height'].plot()
<class 'matplotlib.axes._subplots.AxesSubplot'>
<AxesSubplot:>
차트의 종류를 다양하게 나타낼 수 있다.
- data['height'].plot(kind='hist') --- 타입이 series (pandas 내장 객체임)
- plt.hist(data['height']) --- 타입이 tuple (matplot 함수)
pandas 내장 객체 함수 plot 사용
print(type(data['height'].plot(kind='hist')))
data['height'].plot(kind='hist')
<class 'matplotlib.axes._subplots.AxesSubplot'>
<AxesSubplot:ylabel='Frequency'>
matplot 라이브러리 함수 사용
import matplotlib.pyplot as plt
print(type(plt.hist(data['height'])))
plt.hist(data['height'])
<class 'tuple'>
(array([ 1., 2., 3., 5., 3., 6., 12., 3., 5., 2.]),
array([163., 166., 169., 172., 175., 178., 181., 184., 187., 190., 193.]),
<BarContainer object of 10 artists>)
data['height'].plot(kind='bar')
<AxesSubplot:>
data['height'].plot(kind='density')
<AxesSubplot:ylabel='Density'>
data['height'].plot(kind='box')
<AxesSubplot:>