Learn & Record
Python (넘파이 Numpy, 배열 생성, 배열의 연산, 배열 인덱싱과 슬라이싱, 판다스 Pandas) 본문
- Pandas 라이브러리 설치 (Numpy도 자동으로 설치됨)
1. 넘파이 Numpy
- 배열 데이터를 효과적으로 다룰 때 사용
- 파이썬으로 과학 연산을 쉽고 빠르게 할 수 있게 만든 패키지
- Numpy를 이용하면 파이썬의 기본 데이터 형식과 내장 함수를 이용하는 것보다 다차원 데이터를 효과적으로 처리 가능
- Numpy 홈페이지 : http://numpy.org/
NumPy -
Use the interactive shell to try NumPy in the browser
numpy.org
- 배열 Array 이란 1) 순서가 있는 2) 같은 종류의 데이터가 저장된 집합
- Numpy를 이용해 배열을 처리하기 위해서는 우선 Numpy로 배열을 생성해야 함
- 다양한 방법으로 배열 생성
# 1. 배열 생성하기
# Numpy는 파이썬의 내장 모듈이 아니라서 별도로 설치
import numpy as np
# 1) 시퀀스 데이터로 부터 배열 생성하기. array()
# 시퀀스 데이터 seq_data를 인자로 받아 Numpy의 배열 객체 array object를 생성
# arr_obj = np.array(seq_data)
data1 = [0,1,2,3,4,5]
print(data1) # [0,1,2,3,4,5]
a1 = np.array(data1)
print(a1) # [0 1 2 3 4 5]
print(a1.dtype) # data type이 int 32
# 정수와 실수가 혼합된 경우
data2 = [0.1, 5, 4, 12, 0.5]
a2 = np.array(data2)
print(a2) # [ 0.1 5. 4. 12. 0.5 ]
print(a2.dtype) # float64. 정수와 실수가 혼합돼 있을 때 모두 실수로 변환
# 숫자와 문자가 있는 경우
data3 = [0.1, 5, 4, 12, 'test']
a3 = np.array(data3)
print(a3) # ['0.1', '5', '4', '12', 'test']
print(a3.dtype) # <U32 -> 길이가 32인 유니코드 문자열
# array()에 직접 리스트를 넣어서 배열 객체도 생성 가능
a3 = np.array([0.5, 2, 0.01, 0])
print(a3) # [0.5, 2. 0.01 0 ]
# 다차원 배열의 생성 예
a4 = np.array([[1,2,3], [4,5,6], [7,8,9]])
print(a4)
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
# 2) 범위를 저장해 배열 생성. arange()
# arange()를 이용해 Numpy 배열을 생성. 파이썬의 range()와 사용방법이 비슷
# arr_obj = np.arange([start,] stop[, step])
# start부터 시작해서 stop 전까지 step 만큼 계속 더해 NumPy 배열을 생성
# start가 0인 경우에는 생략가능
# step이 1인 경우에는 생략가능
a1 = np.arange(0, 10, 2)
print(a1) # [0 2 4 6 8]
a2 = np.arange(1, 10)
print(a2) # [1 2 3 4 5 6 7 8 9]
a3 = np.arange(5)
print(a3) # [0 1 2 3 4]
# NumPy 배열의 arange()를 이용해 생성한 1차원 배열에 reshape(m, n)을 추가하면 m*n 형태의 2차원 배열(행렬)로 변경
# 주의할 점은 arange()로 생성되는 배열의 원소 개수와 reshape(m, n)의 m*n의 개수가 같아야 함
a4 = np.arange(12).reshape(4,3)
print(a4)
# NumPy 배열의 형태를 알기 위해서는 'ndarray.shape'를 실행
print(a4.shape) # (4,3)
# 1차원 배열의 경우 '(n, )'처럼 표시
print(a1.shape) # (5,)
# ndarray.linspace()
# 범위의 시작과 끝을 지정하고 데이터의 개수를 지정해 배열을 생성
# arr_obj = np.linspace(start, stop[, num])
# linspace()는 start부터 stop까지 num개의 배열을 같은 간격으로 생성. num을 지정하지 않으면 50이 기본값
a1 = np.linspace(1, 10, 10)
print(a1) # [ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. ]
a2 = np.linspace(1, 10, 4)
print(a2) # [1. 4. 7. 10.] 간격이 3
# 0부터 파이까지 동일한 가격으로 20개를 나눈 배열 생성
a3 = np.linspace(1, np.pi, 20)
print(a3)
# [1. 1.1127154 1.22543081 1.33814621 1.45086161 1.56357701
# 1.67629242 1.78900782 1.90172322 2.01443863 2.12715403 2.23986943
# 2.35258483 2.46530024 2.57801564 2.69073104 2.80344645 2.91616185
# 3.02887725 3.14159265]
# 3) 특별한 형태의 배열 생성
# 모든 원소가 0 혹인 1인 다차원 배열을 만들기 위해서는 zeros()와 ones()를 이용
# 원소가 0이고 개수가 10개인 1차원 배열 생성
a1 = np.zeros(10)
print(a1)
# 3 * 4의 2차원 배열을 생성
a2 = np.zeros((3,4))
print(a2)
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
a3 = np.ones(5)
print(a3) # [1. 1. 1. 1. 1.]
# 4) 배열의 데이터 타입 변환
# 배열은 숫자뿐만 아니라 문자열도 원소를 가질 수 있음
# 문자열이 원소인 배열 생성 예
a1 = np.array(['1.5', '0.62', '2', '3.14', '3.141592'])
print(a1) # ['1.5' '0.62' '2' '3.14' '3.141592']
print(a1.dtype) # <U8. 데이터 형식이 유니코드이며 문자의 수는 최대 8개라는 것을 의미
# NumPy 데이터의 형식.
# b : 불. bool
# i : 기호가 있는 정수. (signed) integer
# u : 기호가 없는 정수. unsigned integer
# f : 실수. floating-point
# c : 복소수. complex-floating point
# M : 날짜. datetime
# O : 파이썬 객체. (Python) objects
# S or a : 바이트 문자열. (byte) string
# U : 유니코드. Unicode
# 배열이 문자열(숫자 표시)로 돼 있다면 연산을 위해서는 문자열을 숫자(정수나 실수)로 변환해야 함
# 형 변환은 astype()로 가능
# num_arr = str_arr.astype(dtype)
# 실수가 입력된 문자열을 원소로 갖는 배열을 실수타입으로 변환하는 예
str_a1 = np.array(['1.567', '0.123', '5.123', '9', '0'])
num_a1 = str_a1.astype(float)
print(num_a1) # [1.567 0.123 5.123 9. 0. ]
print(str_a1.dtype) # <U5
print(num_a1.dtype) # float64
# 정수를 문자열 워소로 갖는 배열을 정수로 변환하는 예
str_a2 = np.array(['1', '3', '5', '7', '9'])
num_a2 = str_a2.astype(int)
print(num_a2)
print(str_a2.dtype)
print(num_a2.dtype)
# 5) 난수 배열의 생성
# NumPy에서 난수를 발생시킬 수 있는 다양한 함수가 있음
# rand() 함수를 이용하며 실수 난수를 요소로 갖는 배열을 생성
# randint() 함수를 이용하면 정수 난수를 요소로 갖는 배열을 생성
# rand_num = np.random.rand([d0, d1 ..., dn])
# rand_num = np.random.randint([low,] high [, size])
# rand() 함수는 [0,1) 사이의 시수 난수를 갖는 배열을 생성
# * [a,b)의 펴현은 값의 범위가 a이상이고 b 미만이라는 의미
# randint() 함수는 [low, high) 사이의 정수 난수를 갖는 배열을 생성
# size는 배열의 형태 지정
# low가 입력하지 않으면 0으로 간주
# size가 입력되지 않으면 1로 간주
a1 = np.random.rand(2, 3)
print(a1)
# [[0.04033988 0.92889488 0.50857354]
# [0.78680406 0.68580141 0.68657928]]
a3 = np.random.rand(1, 2, 3)
print(a3)
# [[0.24795877 0.63317149 0.19529521]
# [0.26287849 0.44237606 0.93189269]]
# [[[0.31005606 0.45917568 0.51642832]
# [0.35282887 0.49928523 0.89060892]]]
a4 = np.random.randint(10, size=(3,4)) # 0부터 9까지의 정수 난수를 요소로 가지는 3 * 4 배열을 생성
print(a4)
a5 = np.random.randint(1, 30)
print(a5)
a6 = np.random.randint(1, 30, 3)
print(a6) # [ 6 14 8]
- 2. 배열의 연산
# 1) 기본 연산
# 배열의 형태 shape가 같다면 덧셈과 뺄셈, 곱셈과 나눗셈 연산을 할 수 있음
arr1 = np.array([10, 20, 30, 40])
arr2 = np.array([1, 2, 3, 4])
# 각 배열의 같은 위치의 원소끼리 더함
print(arr1 + arr2) # [11 22 33 44]
# 두 배열의 차는 같은 위치의 원소끼리 뺌
print(arr1 - arr2) # [ 9 18 27 36 ]
# 배열에 상수를 곱하면 각 원소에 상수를 곱함
print(arr1 * 2) # [20 40 60 80 ]
# 배열의 거듭제곱은 배열의 각 원소에 거듭제곱
print(arr1 ** 2) # [100 400 900 1600 ]
# 두 배열끼리의 곱셈은 각 원소끼리 곱함
print(arr1 * arr2) # [ 10 40 90 160 ]
# 두 배열의 나눗세은 각 원소끼리 나눔
print(arr1 / arr2) # [10. 10. 10. 10.]
# 배열은 비교 연산도 가능. 원소별로 조건과 일치하는지 검사한 후 일치하면 True를, 그렇지 않으면 False를 반환
print(arr1 > 20) # [False False True True]
# 2) 통계를 위한 연산
# NumPy에는 배열의 합, 평균, 표준 편차, 분산, 최솟값, 최댓값, 누적 곱 등 주로 통계에서 많이 이용하는 메서드가 있음
# 각각 sum(), mean(), std(), var(), min(), max(), cumsum(), cumprod()
arr3 = np.arange(5)
print(arr3) # [0 1 2 3 4]
# 합
print(arr3.sum()) # 10
# 평균
print(arr3.mean) # 2.0
# 표준 편차
print(arr3.std()) # 1.4142135623730951
# 분산
print(arr3.var()) # 2.0
# 최솟값
print(arr3.min()) # 0
# 최댓값
print(arr3.max()) # 4
arr4 =np.arange(1, 5)
print(arr4) # [1 2 3 4]
# 누적 합
print(arr4.cumsum()) #[ 1 3 6 10]
# 누적 곱
print(arr4.cumprod()) #[ 1 2 6 24]
- 3. 배열의 인덱싱과 슬라이싱
# 배열의 인덱싱
# 1차원 배열에서 특정 위치의 원소를 선택하려면 원소의 위치를 지정
# 배열명[위치]
# 배열 원소의 위치는 0부터 시작
import numpy as np
a1 = np.array([0, 10, 20, 30, 40, 50])
print(a1[0])
print(a1[4])
# 배열을 변경
a1[5] = 70
print(a1) # [0 10 20 30 40 70]
# 1차원 배열에서 여러 개의 원소를 선택
# 배열명[위치1, 위치2, ... , 위치n]
print(a1[[1,3,4]]) # [10 30 40]
# 2차원 배열에서 특정 위치의 원소를 선택하려면 행과 열의 위치를 지정
# 배열명[행_위치, 열_위치]
a2 = np.arange(10, 100, 10).reshape(3,3)
print(a2)
# [[10 20 30]
# [40 50 60]
# [70 80 90]]
# 행 위치가 0이고, 열 위치가 2인 원소를 반환
print(a2[0, 2]) # 30
print(a2[0][2])
# 2차원 배열의 행과 열의 위치를 지정해서 원소를 선택한 후 값을 변경할 수 있음
a2[2,2] = 95
print(a2)
# [[10 20 30]
# [40 50 60]
# [70 80 95]]
# 2차원 배열의 여러 원소를 선택하기 위해서 아래와 같이 지정
# 배열명[행.위치1, 행,위치2, ... , 행.위치n], [열_위치1, 열_위치2, ... , 열_위치n]]
print(a2[[0,2], [0,1]])
# [10 00]
# 배열에 조건을 지정해 조건을 만족하는 배열을 선택
# 배열명[조건]
a = np.array([1, 2, 3, 4, 5, 6])
print(a[a > 3]) # [4 5 6]
# 짝수만 선택하는 예
print(a[(a % 2) == 0]) # [2 4 6]
# -인덱스도 사용가능
print(a1[-2]) # 40
# 2) 배열의 슬라이싱
# 1차원 배열의 경우 슬라이싱은 배열의 시작과 끝 위치를 지정
# 배열[시작_위치:끝_위치]
# 변환되는 원소의 범위는 '시작_위치 ~ 끝_위치 - 1'
# 시작 위치를 지정하지 않으면 0.
# 끝 위치를 지정하지 않으면 배열이 기이
b1 = np.array([0, 10, 20, 30, 40, 50])
print(b1[1:4]) # [10 20 30]. 1 ~ 3
# 1차원 배열에서 '시작_위치'와 '끝_위치'를 지정하지 않고 슬라이싱하는 예
print(b1[:3]) # [ 0 10 20]. 0 ~ 2
print(b1[2:]) # [ 20 30 40 50]. 2 ~
print(b1[:]) # [ 0 10 20 30 40 50]
# 슬라이싱을 이용해 원소를 변경할 수 있음
b1[2:5] = np.array([25, 35, 45])
print(b1) # [ 0 10 25 60 60 60]. 3~5 변경
- 연습문제
# 넘파이 배열을 사용하여 1부터 20까지의 연속된 정수값을 가지는 1차원 배열을 생성하여
# 실행결과와 같이 출력되기 위해 알맞은 코드를 쓰시오.
# 마지막 원소 : 20
# 모든 원소의 합 : 210
# 모든 원소의 평균 : 10.5
# [[ 1 2 3 4 5]
# [ 6 7 8 9 10]
# [11 12 13 14 15]
# [16 17 18 19 20]]
a1 = np.arange(1,21)
print(f'마지막 원소 : {a1[-1]}')
print(f'모든 원소의 합 : {a1.sum()}')
print(f'모든 원소의 평균 : {a1.mean()}')
print(a1.reshape(4,5))
- 연습문제2
# 학생들의 근로 장학금이 넘파이 배열에 저장되어 있다.
# 이번 학기 학생들의 근로장학금을 1.5배 올려주려고 한다.
# 다음은 인상된 근로장학금을 출력하고 근로장학금이 평균 근로장학금보다 많은 학생들의 근로장학금을 출력하고
# 원소의 수를 출력하는 프로그램이다.
import numpy as np
salary = [200, 150, 180, 220, 250]
# 인상된 금액 : [300. 225. 270. 330. 375.]
# 평균 금액 : 300.0
# 평균이상인 원소 : [300. 330. 375.]
# 평균이상인 원소의 개수 : 3
salary= np.array(salary)
up_salary = salary*1.5
print(f'인상된 금액 : {up_salary}')
print(f'평균 금액 : {up_salary.mean()}')
print(f'평균이상인 원소 : {up_salary[up_salary>=up_salary.mean()]}')
print(f'평균이상인 원소의 개수 : {up_salary[up_salary>=up_salary.mean()].size}')
2. 판다스 Pandas
- 파이썬에서 데이터 분석과 처리를 쉽게 처리할 수 있게 도와줌
- Numpy를 기반으로 만들어졌지만 좀 더 복잡한 데이터 분석에 특화
- Numpy가 같은 데이터 타입의 배열만 처리할 수 있는데 반해 pandas는 데이터 타입이 다양하게 섞여 있어도 처리 가능
- 공식 홈페이지 : https://pandas.pydata.org/
- 1. 구조적 데이터 생성하기
- pandas에서 데이터를 생성하는 가장 기본적인 방법은 Series()를 이용하는 것
- Series()를 이용하면 Series 형식의 구조적 데이터(라벨을 갖는 1차원 데이터)를 생성할 수 있음
- 다음은 Series()를 이용해 Series 형식의 데이터를 생성하는 방법
- s = pd.Series(seq_data)
- Series()의 인자로는 시퀀스 데이터가 들어감
- 시퀀스 데이터로는 리스트와 튜플 타입의 데이터를 모두 사용할 수 있지만 주로 리스트 데이터를 이용
# 1) Series를 활용한 데이터 생성
import pandas as pd
s1 = pd.Series([10, 20, 30, 40, 50])
print(s1)
# 0 10
# 1 20
# 2 30
# 3 40
# 4 50
# dtype: int64
공부 과정을 정리한 것이라 내용이 부족할 수 있습니다.
부족한 내용은 추가 자료들로 보충해주시면 좋을 것 같습니다.
읽어주셔서 감사합니다 :)