DATA ANALYSIS/TIL

[Day18] 데이터 핸들링(1)

yel1nk 2023. 5. 23. 00:50

Numpy

  • 배열 -> 행렬 (선형대수)
import numpy as np
a = np.array([[1, 2], [3, 4]])  # 2차원 배열 생성

print(a.shape)  # 배열 축의 크기 -> (행, 열)
# (2, 2)
print(a.ndim)   # 배열의 차원
# 2
print(a.dtype)  # 배열의 데이터 타입
# int64
print(a.itemsize)  # 각 요소의 바이트 단위 크기
# 8
print(a.nbytes)
# 32
print(np.array(range(2, 11, 2)))
# [ 2  4  6  8 10]
print(np.arange(10, 2, -.5))
# [10.   9.5  9.   8.5  8.   7.5  7.   6.5  6.   5.5  5.   4.5  4.   3.5  3.   2.5]
# 0차원: 스칼라 - 하나의 숫자값
s = np.array(1)

# 1차원: 벡터(Vector)
v = np.array([1, 2, 3])

# 2차원: 행렬(Matrix)
m = np.array([[1, 2, 3], [1, 2, 3]])

# 3차원: 텐서(Tensor)
t = np.array([[[1, 2], [1, 2]], [[1, 2], [1, 2]]])

데이터 타입

숫자형

  • 부호가 있는 정수(signed integer)
  • 부호가 없는 정수(unsigned integer)
  • 실수(floating point)
  • 복소수(complex)
# int
i = np.array([1.1, 2, 3], dtype=np.int32)
print(i)
# [1 2 3]

# uint
ui = np.array([-1, 2, 3], dtype=np.uint32)  # [0 ~ 4,294,967,295]
print(ui)
# [4294967295          2          3]

# float
f = np.array([1.1, 2, 3], dtype=np.float64)  # dtype='f'
print(f)  # 소수점 0 생략 
# [1.1 2.  3. ]

# complex
c = np.array([1 + 2j, 3 + 4j, 5 + 6j], dtype=np.complex64)
print(c)
print(c.real)  # 실수 
print(c.imag)  # 허수 
# [1.+2.j 3.+4.j 5.+6.j]
# [1. 3. 5.]
# [2. 4. 6.]

문자형

  • string_
  • unicode_ : 가독성이 좋지만 데이터 크기가 더 큼
# string 
s = np.string_([1, 2, 3])
print(s)  # byte 단위 표시 
print(s.dtype)  # S3 : string 3
# b'\x01\x02\x03'
# |S3

s2 = np.array([1, 2, 3, 4, 5], dtype='S')
print(s2)
print(s2.dtype)
# [b'1' b'2' b'3' b'4' b'5']
# |S1

# unicode 
u = np.unicode_([1, 2, 3, 4, 5])
print(u)
print(u.dtype)
# [1, 2, 3, 4, 5]
# <U15

u2 = np.array([11, 22, 33, 44, 55], dtype='U')
print(u2)
print(u2.dtype)
# ['11' '22' '33' '44' '55']
# <U2

논리형 (boolean)

  • True(1), False(0)
  • 비트 연산 사용 : & and, | or, ^ xor, ~not
l1 = np.array([True, False, True])
l2 = np.array([False, True, False])
and_ = np.logical_and(l1, l2)
print(and_)
# [False False False]

데이터 형 변환 (Cast, Casting 형 변환)

  • 데이터들끼리 형태를 맞춰줌
  • ex) 이미지 데이터 -> uint 형으로 불러옴 -> float
data = [1.1, 2, 3]
a = np.float64(data) 
print(a)
print(a.dtype)
# [1.1 2.  3. ]
# float64

a = a.astype(np.int64)
print(a)
print(a.dtype)
# [1 2 3]
# int64

b = np.uint16(0)
print(b)
print(b.dtype)
# 0
# uint16

b = b - 1  # 알아서 형 변환됨
print(b)
print(b.dtype)
# -1
# int64

c = np.uint16(-1)  # uint16 [0 ~ 65,535]
print(c)
print(c.dtype)
# 65535
# uint16

산술연산

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

aa = np.exp(a) # 지수함수
print(aa)
# [ 2.71828183  7.3890561  20.08553692]

bb = np.log(b) # 자연로그 
print(bb)
# [1.38629436 1.60943791 1.79175947]

cc = np.log2(b) # 밑이 2인 로그 
print(cc)
# [2.         2.32192809 2.5849625 ]

d = np.array([0, np.pi/2, np.pi])
sin_ = np.sin(d)
cos_ = np.cos(d)
tan_ = np.tan(d)
print(d)
print(sin_)
print(cos_)
print(tan_)
# [0.         1.57079633 3.14159265]
# [0.0000000e+00 1.0000000e+00 1.2246468e-16]
# [ 1.000000e+00  6.123234e-17 -1.000000e+00]
# [ 0.00000000e+00  1.63312394e+16 -1.22464680e-16]

배열의 연결과 분할

배열 연결

  • 열이 늘어남 → hstack, axis = 1
  • 행이 늘어남 → vstack, axis = 0

배열 분할

  • 열 방향으로 자름 → hsplit
  • 행 방향으로 자름 → vsplit

axis를 배열 분할에 적용할 때는

  • 열 방향으로 자름 → axis = 0
  • 행 방향으로 자름 → axis = 1
x2 = [[1, 2], 
      [3, 4]] 
y2 = [[4, 5], 
      [6, 7]]

v = np.concatenate([x2, y2], axis=0)  # 행 병합
v = np.vstack([x2, y2]) # vstack - vertical 수직 
print(v) 
# [[1 2]
#  [3 4]
#  [4 5]
#  [6 7]]

h = np.concatenate([x2, y2], axis=1)  # 열 병합
h = np.hstack([x2, y2]) # hstack - horizontal 수평
print(h)
# [[1 2 4 5]
#  [3 4 6 7]]
# 분할할 배열 생성
arr = np.arange(1, 13).reshape((3, 4))

# 1. 수평분할하기 -> 다시 원본으로 스택쌓기
arr_split = np.hsplit(arr, 2)
arr_1 = arr_split[0]
arr_2 = arr_split[1]
arr_stack = np.hstack((arr_1, arr_2))

# 2. 수직분할하기 -> 다시 원본으로 스택쌓기
arr_split = np.vsplit(arr, 3)
arr_1 = arr_split[0]
arr_2 = arr_split[1]
arr_3 = arr_split[2]
arr_stack = np.vstack((arr_1, arr_2, arr_3))

다양한 배열 만들기

# 0으로 채워진 배열 생성 
zero = np.zeros([3, 2, 4])

# 1로 채워진 배열 생성 
one = np.ones([3, 4])

# 원하는 값으로 채워진 배열 생성 
f = np.full([2, 3], 10)

# 대각 행렬 - nxn(정방형) 행렬만 가능
eye = np.eye(3)

# 일차원으로 변경 
arr_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(arr_3d.ravel())
# [1 2 3 4 5 6 7 8]

# 0에서 1사이의 값으로 크기 10개의 1차원 배열을 만들어주세요.
l = np.linspace(0, 1, 10)
print(l)
# [0.         0.11111111 0.22222222 0.33333333 0.44444444 
# 0.55555556 0.66666667 0.77777778 0.88888889 1.        ]

제공함수

범용함수

arr1 = np.array([-1, -2, -3, -4])
abs_arr = np.abs(arr1)

arr2 = np.array([1, 4, 9, 16])
sqrt_arr = np.sqrt(arr2)

집계함수

a = np.array([1, 2, 3, 4, 5]) 
a_mean = np.mean(a) # 평균값 : 3.0
a_median = np.median(a) # 중간값 : 3.0
a_std = np.std(a) # 표준편차 : 1.4142135623730951
a_var = np.var(a) # 분산 : 2.0
a_sum = np.sum(a) # 단순 합계 : 15
a_cumsum = np.cumsum(a) # 누적 합계 : [ 1  3  6 10 15]

# argmin, argmax -> index 값 반환 
min = np.argmin(d) # 0
max = np.argmax(d) # 4

# any, all -> boolean
a = np.array([0, 0, 0, 1])
a_true = np.any(a) # True
a_all = np.all(a) # False

# NaN (Not a Number)
a = np.array([1, 2, np.nan, 4])
a_nsum = np.nansum(a) # 7.0
a_sum = np.sum(a) # nan

# condition
d = np.array([1, 2, 3, 4, 5])
condition = np.where(d < 3) # (array([0, 1]),)
condition1 = np.where(d < 3, d, 0) # [1 2 0 0 0]
arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
                
# 각 열의 평균값을 계산하여 새로운 1차원 배열로 나타내세요.                
m = np.mean(arr, axis=0)
print(m)
# [4. 5. 6.]

# 각 행의 최대값을 구하여 1차원 배열로 반환하세요.
max = np.max(arr, axis=1)
print(max)
# [3 6 9]
# 조건함수를 사용해서 짝수조건을 만족하는 요소의 값이 2배로 만드는 배열을 만드시오.
arr = np.array([1, 2, 3, 4, 5])
arr1 = np.where(arr % 2 == 0, arr * 2, arr)
print(arr1)
# [1 4 3 8 5]

Boolean Indexing

  • 조건에 따른 요소들을 판별해서 새로운 배열을 만든다.
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # 원본 데이터는 그대로 
# a = np.arange(1, 11)

even_a = a[a % 2 == 0]
print(even_a)
# [ 2  4  6  8 10]

Broadcast

  • 크기가 다른 배열 간의 연산도 가능하게 한다.
  • 두 배열의 차원 수가 다를 경우, 더 작은 차원의 배열에 큰 차원의 배열이 맞을 때까지 1을 추가한다.
  • 두 배열의 차원 수가 같을 경우에도, 크기가 1인 차원이 있다면 다른 배열의 크기와 일치하도록 복제된다.
  • 두 배열의 차원 수가 같을 경우에도, 모든 차원의 크기가 같거나 크기가 1이라면 모양이 같은 두 배열의 요소 간 연산을 한다.
d = np.array([[1], [2], [3]])  # 행렬 3x1
e = np.array([4, 5, 6])        # 벡터 
# e = np.array([[4, 5, 6]])    # 행렬 1x3

f = d + e  # 행렬 3x3
print(f)
# [[5 6 7]
#  [6 7 8]
#  [7 8 9]]

행렬의 곱

  • * 연산자
  • @ 연산자 (np.dot)
# 2x2 2x2
a = np.array(
    [[1, 2],
     [3, 4]])

b = np.array(
    [[1, 2],
     [3, 4]])

print(a*b)
'''
[[ 1  4]
 [ 9 16]]
'''
 
print(a@b)
print(np.dot(a, b))
'''
[[ 7 10]
 [15 22]]
'''
# 3x2 2x3
a = np.array(
    [[1, 2],
     [3, 4],
     [5, 6]])

b = np.array(
    [[1, 2, 3],
     [4, 5, 6]])

# print(a*b) # error

print(a@b)
print(np.dot(a, b))
'''
[[ 9 12 15]
 [19 26 33]
 [29 40 51]]
'''

'DATA ANALYSIS > TIL' 카테고리의 다른 글

[Day20] 데이터 핸들링(3)  (0) 2023.05.24
[Day19] 데이터 핸들링(2)  (0) 2023.05.24
[Day 17] Python 심화(7)  (0) 2023.05.18
[Day15] Python 심화(6)  (0) 2023.05.17
[Day14] Python 심화(5)  (0) 2023.05.16