day 7 파이썬 배열(array)과 표(table)

18 minute read

파이썬 배열(array)과 표(table)

배열

평균 계산하기

total = 0
count = 0
numbers = input("Enter a number :  (<Enter Key> to quit)")
while numbers != "":
    try:
        x = float(numbers)
        count += 1
        total = total + x
    except ValueError:
        print('NOT a number! Ignored..')
    numbers = input("Enter a number :  (<Enter Key> to quit)")
avg = total / count
print("\n average is", avg)
..
..
Enter a number :  (<Enter Key> to quit) 1
Enter a number :  (<Enter Key> to quit) 1
Enter a number :  (<Enter Key> to quit) 3
Enter a number :  (<Enter Key> to quit) 4
Enter a number :  (<Enter Key> to quit) 
average is 2.25

평균, 표준편차, 중앙값 계산

image

# 2개 이상의 숫자를 입력받아 리스트에 저장하는 함수
def numbers():
    X=[]    # X에 빈 리스트를 할당합니다.
    while True:
        number = input("Enter a number (<Enter key> to quit)") 
        while number !="":
            try:
                x = float(number)
                X.append(x)    # float형으로 변환한 숫자 입력을 리스트에 추가합니다.
            except ValueError:
                print('>>> NOT a number! Ignored..')
            number = input("Enter a number (<Enter key> to quit)")
        if len(X) > 1:  # 저장된 숫자가 2개 이상일 때만 리턴합니다.
            return X

X=numbers()

print('X :', X)
..
..
Enter a number (<Enter key> to quit) 1
Enter a number (<Enter key> to quit) 2
Enter a number (<Enter key> to quit) 3
Enter a number (<Enter key> to quit) 
X : [1.0, 2.0, 3.0]

다른 언어에서는 배열은 크기를 정해 놓아야 하는 경우가 많습니다. 대표적으로 C언어가 그러하지요. 그러니깐, 배열 변수를 만들 때 처음에 원소가 몇 개 들어갈 수 있다고 정해놓아야 합니다. 그러나 파이썬의 리스트는 그렇지 않습니다. 파이썬의 리스트는 임의의 데이터 타입을 담을 수 있는 가변적 연속열(Sequence)형입니다. 즉, 파이썬 리스트는 동적 배열(Dynamic Array) 입니다.

import array as arr

mylist = [1, 2, 3]   # 이것은 파이썬 built-in list입니다. 
print(type(mylist))

mylist.append('4')  # mylist의 끝에 character '4'를 추가합니다. 
print(mylist)

mylist.insert(1, 5)  # mylist의 두번째 자리에 5를 끼워넣습니다.
print(mylist)

myarray = arr.array('i', [1, 2, 3])   # 이것은 array입니다. import array를 해야 쓸 수 있습니다.
print(type(myarray))

# 아래 라인의 주석을 풀고 실행하면 에러가 납니다.
#myarray.append('4')    # myarray의 끝에 character '4'를 추가합니다. 
print(myarray)

myarray.insert(1, 5)    # myarray의 두번째 자리에 5를 끼워넣습니다.
print(myarray)

  • list는 별도의 import가 필요없지만 array를 사용하기 위해서는 import를 해주어야 합니다. 파이썬에서 array는 built-in이 아닙니다.

  • list 안의 element 사이에 다른 타입의 자료형이 허용됩니다. 숫자로만 이루어진 list에 문자열 element를 추가할 수 있습니다. 그러나 array는 처음부터 element의 유형을 지정해서 생성하며, 지정되지 않은 다른 타입의 element 추가가 허용되지 않습니다. 이러한 array의 특성은 다음에 나오는 NumPy에도 동일하게 적용됩니다.

리스트를 활용한 시그마의 표현

total = 0.0
for i in range(len(X)):
    total = total + X[i]
mean = total / len(X)

print('sum of X: ', total)
..
..
sum of X:  6.0

중앙값

def median(nums):  		# nums : 리스트를 지정하는 매개변수
    nums.sort()					# sort()로 리스트를 순서대로 정렬
    size = len(nums)
    p = size // 2
    if size % 2 == 0:		   # 리스트의 개수가 짝수일때 
        pr = p                         # 4번째 값
        pl = p-1                      # 3번째 값
        mid= float((nums[pl]+nums[pr])/2)    
    else:								# 리스트의 개수가 홀수일때
        mid = nums[p]
    return mid

print('X :', X)
median(X)						# 매개변수의 값으로 X를 사용함
..
..
X : [1.0, 2.0, 3.0]
2.0

표준편차와 평균

def means(nums):
    total = 0.0
    for i in range(len(nums)):
        total = total + nums[i]
    return total / len(nums)

means(X)
..
..
2.0

avg = means(X)

def std_dev(nums, avg):
   texp = 0.0
   for i in range(len(nums)):
       texp = texp + (nums[i] - avg)**2    # 각 숫자와 평균값의 차이의 제곱을 계속 더한 후
   return (texp/(len(nums)-1)) ** 0.5    # 그 총합을 숫자개수-1로 나눈 값의 제곱근을 리턴합니다.

std_dev(X,avg)
..
..
1.0

전체 코드 : main()함수

def numbers():
    X=[]
    while True:
        number = input("Enter a number (<Enter key> to quit)") 
        while number !="":
            try:
                x = float(number)
                X.append(x)
            except ValueError:
                print('>>> NOT a number! Ignored..')
            number = input("Enter a number (<Enter key> to quit)")
        if len(X) > 1:
            return X

def median(nums): 
    nums.sort()
    size = len(nums)
    p = size // 2
    if size % 2 == 0:
        pr = p
        pl = p+1
        mid = float((nums[pl]+nums[pr])/2)
    else:
        mid = nums[p]
    return mid

def means(nums):
    total = 0.0
    for i in range(len(nums)):
        total = total + nums[i]
    return total / len(nums)

def std_dev(nums, avg):
   texp = 0.0
   for i in range(len(nums)):
       texp = texp + (nums[i] - avg) ** 2
   return (texp/(len(nums)-1)) ** 0.5

def main():
    X = numbers()
    med = median(X)
    avg = means(X)
    std = std_dev(X, avg)
    print("당신이 입력한 숫자{}의 ".format(X))
    print("중앙값은{}, 평균은{}, 표준편차는{}입니다.".format(med, avg, std))

if __name__ == '__main__':
    main()


med = median(X)
avg = means(X)
std = std_dev(X, avg)
print("당신이 입력한 숫자{}의 ".format(X))
print("중앙값은{}, 평균은{}, 표준편차는{}입니다.".format(med, avg, std))
..
..
당신이 입력한 숫자[1.0, 2.0, 3.0]의 
중앙값은2.0, 평균은2.0, 표준편차는1.0입니다.

numpy

우린 NumPy 이야기 해야죠? 여기는 NumPy 공식 사이트에요. 여기에 소개된 NumPy의 특징을 바탕으로 몇 가지 장점을 소개 드리면,

  • 빠르고 메모리를 효율적으로 사용하여 벡터의 산술연산과 브로드캐스팅 연산을 지원하는 다차원 배열 ndarray 데이터 타입을 지원한다.

  • 반복문을 작성할 필요 없이 전체 데이터 배열에 대해 빠른 연산을 제공하는 다양한 표준 수학 함수를 제공한다.

  • 배열 데이터를 디스크에 쓰거나 읽을 수 있다. (즉, 파일로 저장한다는 뜻입니다)

  • 선형대수, 난수발생기, 푸리에 변환 가능, C/C++ 포트란으로 쓰여진 코드를 통합한다.

import numpy as np

# 아래 A와 B는 결과적으로 같은 ndarray 객체를 생성합니다. 
A = np.arange(5)
B = np.array([0,1,2,3,4])  # 파이썬 리스트를 numpy ndarray로 변환

# 하지만 C는 좀 다를 것입니다. 
C = np.array([0,1,2,3,'4'])

# D도 A, B와 같은 결과를 내겠지만, B의 방법을 권합니다. 
D = np.ndarray((5,), np.int64, np.array([0,1,2,3,4]))

print(A)
print(type(A))
print(B)
print(type(B))
print(C)
print(type(C))
print(D)
print(type(D))
..
..
[0 1 2 3 4]
<class 'numpy.ndarray'>
[0 1 2 3 4]
<class 'numpy.ndarray'>
['0' '1' '2' '3' '4']
<class 'numpy.ndarray'>
[0 1 2 3 4]
<class 'numpy.ndarray'>

크기 (size, shape, ndim)

size, shape, ndim는 각각 행렬 내 원소의 개수, 행렬의 모양, 행렬의 축(axis)의 개수를 의미합니다. reshape() 메소드는 행렬의 모양를 바꿔줍니다. 모양을 바꾸기 전후 행렬의 총 원소 개수(size)가 맞아야 해요.

A = np.arange(10)
print('A: ', A)
B = np.arange(10).reshape(2,5)
print('B: ', B)
C = np.arange(10).reshape(3,3)  # 이 줄에서 에러가 날 것입니다.
print('C: ', C)
..
..
A:  [0 1 2 3 4 5 6 7 8 9]
B:  [[0 1 2 3 4]
 [5 6 7 8 9]]
----> 5 C = np.arange(10).reshape(3,3)  # 이 줄에서 에러가 날 것입니다.
      6 print('C: ', C)

ValueError: cannot reshape array of size 10 into shape (3,3)

type

A= np.arange(6).reshape(2,3)
print(A)
print(A.dtype)
print(type(A))

B = np.array([0,1,2,3,4,5])  
print(B)
print(B.dtype)
print(type(B))

C = np.array([0,1,2,3,'4',5])
print(C)
print(C.dtype)
print(type(C))

D = np.array([0,1,2,3,[4,5],6])  # 이런 ndarray도 만들어질까요?
print(D)
print(D.dtype)
print(type(D))
..
..
[[0 1 2]
 [3 4 5]]
int64
<class 'numpy.ndarray'>
[0 1 2 3 4 5]
int64
<class 'numpy.ndarray'>
['0' '1' '2' '3' '4' '5']
<U21
<class 'numpy.ndarray'>
[0 1 2 3 list([4, 5]) 6]
object
<class 'numpy.ndarray'>
/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:16: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  app.launch_new_instance()

차이가 느껴지시나요? NumPy의 원소는 꼭 동일한 데이터 type이어야 합니다. NumPy의 메소드인 dtype은 NumPy ndarray의 “원소”의 데이터타입을 반환해요. 반면에 파이썬 내장함수인type(A)을 이용하면 행렬 A의 자료형이 반환됩니다.

여기서 재미있는 것은 D의 경우입니다. 이번에는 원소 하나를 list 객체로 바꿔 보았습니다. 위의 설명대로라면 NumPy의 원소는 꼭 동일한 데이터 type이어야 하므로 이번만큼은 에러가 날줄 알았는데, 떡하니 정상적으로 ndarray가 만들어집니다. 대신 D.dtype은 object를 리턴했습니다. 파이썬의 최상위 클래스는 바로 object입니다. 그러므로 Numpy는 dtype을 object로 지정해서라도 행렬 내 dtype을 일치시킬 수 있게 됩니다.

특수행렬

# 단위행렬
np.eye(3)
..
..
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

# 0 행렬
np.zeros([2,3])
..
..
array([[0., 0., 0.],
       [0., 0., 0.]])

# 1행렬
np.ones([3,3])
..
..
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

브로드캐스트

A = np.arange(9).reshape(3,3)
A
..
..
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

# ndarray A에 2를 더했을 때,
2
A + 2
..
..
array([[ 2,  3,  4],
       [ 5,  6,  7],
       [ 8,  9, 10]])

# 3 X 3 행렬에 1 X 3 행렬을 더했을 때
A = np.arange(9).reshape(3,3)
B = np.array([1, 2, 3])
print(A)
print(B)
A+B
..
..
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[1 2 3]
array([[ 1,  3,  5],
       [ 4,  6,  8],
       [ 7,  9, 11]])

# 3 X 3 행렬에 3 X 1 행렬을 더했을 때
A = np.arange(9).reshape(3,3)
C = np.array([[1], [2], [3]])
print(A)
print(C)
A+C
..
..
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[1]
 [2]
 [3]]
array([[ 1,  2,  3],
       [ 5,  6,  7],
       [ 9, 10, 11]])

# 3 X 3 행렬에 1 X 2 행렬을 더하는 것은 허용되지 않습니다. 
A = np.arange(9).reshape(3,3)
D = np.array([1, 2])
print(A)
print(D)
A+D
..
..
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[1 2]
----> 6 A+D

ValueError: operands could not be broadcast together with shapes (3,3) (2,) 

슬라이스와 인덱싱

# 0, 1을 인덱싱 하면 A의 첫번째 행에서 두번째 값을 참조합니다.
# 아래 두 결과는 정확히 같습니다.
print(A[0, 1])
print(B[1])
..
..
1
2

# 슬라이싱도 비슷합니다.
A[:-1]
array([[0, 1, 2],
       [3, 4, 5]])


# 이 슬라이싱의 결과는 
print(A[:,2:])
print(A[:,1:])
print(A[:,:])

# 이 슬라이싱의 결과와 동일합니다.
print(A[:,-1:])
print(A[:,-2:])
print(A[:,-3:])
..
..
# 위 그림과 비교해서 이해해 보세요.
[[2]
 [5]
 [8]]
[[1 2]
 [4 5]
 [7 8]]
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[2]
 [5]
 [8]]
[[1 2]
 [4 5]
 [7 8]]
[[0 1 2]
 [3 4 5]
 [6 7 8]]

 A[:2, 1:]
 ..
 ..
 array([[1, 2],
       [4, 5]])

# 의사 난수를 생성하는 예제입니다. 여러번 실행해 보세요.

print(np.random.random())   # 0에서 1사이의 실수형 난수 하나를 생성합니다. 

print(np.random.randint(0,10))   # 0~9 사이 1개 정수형 난수 하나를 생성합니다. 

print(np.random.choice([0,1,2,3,4,5,6,7,8,9]))   # 리스트에 주어진 값 중 하나를 랜덤하게 골라줍니다.
..
..
0.2062334447419517
6
8

random

# 의사 난수를 생성하는 예제입니다. 여러번 실행해 보세요.

print(np.random.random())   # 0에서 1사이의 실수형 난수 하나를 생성합니다. 

print(np.random.randint(0,10))   # 0~9 사이 1개 정수형 난수 하나를 생성합니다. 

print(np.random.choice([0,1,2,3,4,5,6,7,8,9]))   # 리스트에 주어진 값 중 하나를 랜덤하게 골라줍니다.
..
..
0.3009068978646956
7
6

# 아래 2가지는 기능면에서 동일합니다. 원소의 순서를 임의로 뒤바꾸어 줍니다. 

print(np.random.permutation(10))   
print(np.random.permutation([0,1,2,3,4,5,6,7,8,9]))
..
..
[4 8 9 3 7 1 6 0 5 2]
[9 4 8 3 7 0 1 6 5 2]

# 아래 기능들은 어떤 분포를 따르는 변수를 임의로 표본추출해 줍니다. 

# 이것은 정규분포를 따릅니다.
print(np.random.normal(loc=0, scale=1, size=5))    # 평균(loc), 표준편차(scale), 추출개수(size)를 조절해 보세요.

# 이것은 균등분포를 따릅니다. 
print(np.random.uniform(low=-1, high=1, size=5))  # 최소(low), 최대(high), 추출개수(size)를 조절해 보세요.
..
..
[ 2.22796335 -2.04576583  0.10470438  0.77453122 -0.17394854]
[ 0.74907527  0.80715109 -0.16315793  0.6109862  -0.79868927]

A = np.arange(24).reshape(2,3,4)
print(A)               # A는 (2,3,4)의 shape를 가진 행렬입니다. 
print(A.T)            # 이것은 A의 전치행렬입니다. 
print(A.T.shape) # A의 전치행렬은 (4,3,2)의 shape를 가진 행렬입니다.
..
..
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
[[[ 0 12]
  [ 4 16]
  [ 8 20]]

 [[ 1 13]
  [ 5 17]
  [ 9 21]]

 [[ 2 14]
  [ 6 18]
  [10 22]]

 [[ 3 15]
  [ 7 19]
  [11 23]]]
(4, 3, 2)

# np.transpose는 행렬의 축을 어떻게 변환해 줄지 임의로 지정해 줄 수 있는 일반적인 행렬 전치 함수입니다. 
# np.transpose(A, (2,1,0)) 은 A.T와 정확히 같습니다.

B = np.transpose(A, (2,0,1))
print(A)             # A는 (2,3,4)의 shape를 가진 행렬입니다. 
print(B)             # B는 A의 3, 1, 2번째 축을 자신의 1, 2, 3번째 축으로 가진 행렬입니다.
print(B.shape)  # B는 (4,2,3)의 shape를 가진 행렬입니다.
..
..
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
[[[ 0  4  8]
  [12 16 20]]

 [[ 1  5  9]
  [13 17 21]]

 [[ 2  6 10]
  [14 18 22]]

 [[ 3  7 11]
  [15 19 23]]]
(4, 2, 3)

기본 통계 데이터 계산 해보기

import numpy as np

# 6-3 스텝에서 사용하였던 함수입니다. 
def numbers():
    X = []
    number = input("Enter a number (<Enter key> to quit)") 
    # 하지만 2개 이상의 숫자를 받아야 한다는 제약조건을 제외하였습니다.
    while number != "":
        try:
            x = float(number)
            X.append(x)
        except ValueError:
            print('>>> NOT a number! Ignored..')
        number = input("Enter a number (<Enter key> to quit)")
    return X

def main():
    nums = numbers()       # 이것은 파이썬 리스트입니다. 
    num = np.array(nums)   # 리스트를 Numpy ndarray로 변환합니다.
    print("합", num.sum())
    print("평균값",num.mean())
    print("표준편차",num.std())
    print("중앙값",np.median(num))   # num.median() 이 아님에 유의해 주세요.

main()
..
..
Enter a number (<Enter key> to quit) 1
Enter a number (<Enter key> to quit) 3
Enter a number (<Enter key> to quit) 
합 4.0
평균값 2.0
표준편차 1.0
중앙값 2.0

데이터의 행렬

데이터의 행렬 변환

A Visual Intro to NumPy and Data Representation

  • 소리 데이터의 경우 numpy로 1차원 array로 표현합니다. CD음원파일의 경우, 44.1kHz의 샘플링 레이트로 -32767 ~ 32768의 정수 값을 갖습니다.

  • 흑백 이미지의 경우 numpy로 이미지 사이즈의 세로X 가로형태의 행렬(2차원 ndarray)로 나타내고, 각 원소는 픽셀별로 명도(grayscale)를 0~255 의 숫자로 환산하여 표시 합니다. 0은 검정, 255는 흰색입니다.

  • 컬러 이미지의 경우 numpy로 이미지 사이즈의 세로 X 가로형태의 행렬에 Red, Green, Blue계열의 3 색으로 행렬을 3개 만듭니다. 따라서 차원은 3차원 입니다.

  • 자연어(블로그에서는 Language로 표기)의 경우 numpy로 임베딩(Embedding)이라는 과정을 거쳐 ndarray로 표현될 수 있습니다. 블로그의 예시에서는 71,290개의 단어가 들어있는 (문장들로 이루어진) 데이터셋이 있을때, 이를 단어별로 나누고 0 - 71289로 넘버링 했습니다. 이를 토큰화 과정이라고 합니다. 그리고 이 토큰을 50차원의 word2vec embedding 을 통해 [batch_size, sequence_length, embedding_size]의 ndarray로 표현할 수 있습니다.

이미지의 행렬 변환

image

아래 이미지는 동일한 사이즈의 이미지에 대해 픽셀이 1 X 1 (1개)일때 부터 100 X 100 (10,000개)일때 이미지의 해상도를 나타내고 있습니다.

이미지는 수많은 점(픽셀)들로 구성되어 있습니다. 각각의 픽셀은 R, G, B 값 3개 요소의 튜플로 색상이 표시됩니다. (Red, Green, Blue의 값이에요)

흰색(W) : (255,255,255) 검정색(B) : (0, 0, 0) 빨간색(R) : (255, 0, 0) 파란색(B) : (0, 0, 255) 녹색(G) : (0, 128, 0) 노란색(Y) : (255, 255, 0) 보라색(P) : (128, 0, 128) 회색(Gray) : (128, 128, 128)

흑백의 경우에는 Gray 스케일로 나타내는데, 0~255 범위의 숫자 1개의 튜플 값이에요. Color는 투명도를 포함하는 A를 포함해 RGBA 4개로 표시하기도 합니다. 아래 그림처럼, Image의 좌표는 보통 왼쪽 위를 (0, 0)으로 표시하고, 오른쪽과 아래로 내려갈수록 좌표가 증가합니다.

image

이미지와 관련된 파이썬 라이브러리

import PIL
PIL.__version__
..
..
'8.1.0'
  • open : Image.open()

  • size : Image.size

  • filename : Image.filename

  • crop : Image.crop((x0, y0, xt, yt))

  • resize : Image.resize((w,h))

  • save : Image.save()

이미지 저장

$ mkdir -p ~/aiffel/data_represent/image
$ ln -s ~/data/newyork.jpg ~/aiffel/data_represent/image
..
..

from PIL import Image, ImageColor
import os
img_path = os.getenv("HOME") + "/aiffel/data_represent/image/newyork.jpg"
img = Image.open(img_path)
print(img_path)
print(type(img))
img
..
..

image

img.size
(212, 300)

W, H = img.size
print((W, H)
(212, 300)

print(img.format)
print(img.size)
print(img.mode)
JPEG
(212, 300)
RGB

이미지 자르기

이미지를 자를 때에는 .crop() 메소드를 이용합니다

img.crop((30,30,100,100))

image

이미지 저장

자른 이미지를 저장해 보도록 하겠습니다.

# 새로운 이미지 파일명
cropped_img_path = os.getenv("HOME") + "/aiffel/data_represent/image/cropped_img.jpg"
img.crop((30,30,100,100)).save(cropped_img_path)
print("저장 완료!")
..
..
저장 완료!

행렬로 변환

이미지 파일 행렬로 변환

import numpy as np
img_arr = np.array(img)
print(type(img))
print(type(img_arr))
print(img_arr.shape)
print(img_arr.ndim)
..
..
<class 'PIL.JpegImagePlugin.JpegImageFile'>
<class 'numpy.ndarray'>
(300, 212, 3)
3

컬러(RGB)이미지 파일이니 변환된 행렬은 Height X Width X RGB Channel의 모양이고 차원 역시 3차원 입니다.

img_arr
array([[[133, 180, 250],
        [133, 180, 250],
        [133, 180, 250],
        ...,
        [133, 180, 250],
        [133, 180, 250],
        [133, 180, 250]],

       [[133, 180, 250],
        [133, 180, 250],
        [133, 180, 250],
        ...,
        [133, 180, 250],
        [133, 180, 250],
        [133, 180, 250]],

       [[133, 180, 250],
        [133, 180, 250],
        [133, 180, 250],
        ...,
        [133, 180, 250],
        [133, 180, 250],
        [133, 180, 250]],

       ...,

       [[164, 199, 255],
        [164, 199, 255],
        [164, 199, 255],
        ...,
        [164, 199, 255],
        [164, 199, 255],
        [164, 199, 255]],

       [[164, 199, 255],
        [164, 199, 255],
        [164, 199, 255],
        ...,
        [164, 199, 255],
        [164, 199, 255],
        [164, 199, 255]],

       [[164, 199, 255],
        [164, 199, 255],
        [164, 199, 255],
        ...,
        [164, 199, 255],
        [164, 199, 255],
        [164, 199, 255]]], dtype=uint8)

흑백모드

img_g = Image.open(img_path).convert('L')
img_g

image

img_g_arr = np.array(img_g)
print(type(img_g_arr))
print(img_g_arr.shape)
print(img_g_arr.ndim)
..
..
<class 'numpy.ndarray'>
(300, 212)
2

흑백이므로 반환된 행렬은 Height X Width, 차원은 2차원 입니다.

img_g_arr
..
..
array([[174, 174, 174, ..., 174, 174, 174],
       [174, 174, 174, ..., 174, 174, 174],
       [174, 174, 174, ..., 174, 174, 174],
       ...,
       [195, 195, 195, ..., 195, 195, 195],
       [195, 195, 195, ..., 195, 195, 195],
       [195, 195, 195, ..., 195, 195, 195]], dtype=uint8)

get color

red = ImageColor.getcolor('RED','RGB')
reda = ImageColor.getcolor('red','RGBA')
yellow = ImageColor.getcolor('yellow','RGB')
print(red)
print(reda)
print(yellow)
..
..
(255, 0, 0)
(255, 0, 0, 255)
(255, 255, 0)

딥러닝에서 위와 같은 이미지 조작은 Data augmentation의 경우 많이 사용 됩니다.

구조화된 데이터

image

pandas

Series

import pandas as pd
ser = pd.Series(['a','b','c',3])
ser
..
..
0    a
1    b
2    c
3    3
dtype: object

ser.values
..
..
array(['a', 'b', 'c', 3], dtype=object)

ser.index
..
..
RangeIndex(start=0, stop=4, step=1)

ser2 = pd.Series(['a', 'b', 'c', 3], index=['i','j','k','h'])
ser2
..
..
i    a
j    b
k    c
h    3
dtype: object

ser2.index = ['Jhon', 'Steve', 'Jack', 'Bob']
ser2
..
..
Jhon     a
Steve    b
Jack     c
Bob      3
dtype: object

ser2.index
..
..
Index(['Jhon', 'Steve', 'Jack', 'Bob'], dtype='object')

Country_PhoneNumber = {'Korea': 82, 'America': 1, 'Swiss': 41, 'Italy': 39, 'Japan': 81, 'China': 86, 'Rusia': 7}
ser3 = pd.Series(Country_PhoneNumber)
ser3
..
..
Korea      82
America     1
Swiss      41
Italy      39
Japan      81
China      86
Rusia       7
dtype: int64

비단 기본 인덱스 뿐 아니라 값이 할당된 인덱스 형태에 대해서 슬라이싱(slicing) 기능을 지원하기도 하기도 하는 등 특징이 있으니 연습해 두세요.

ser3['Italy':]

Italy 39 Japan 81 China 86 Rusia 7 dtype: int64

Series의 Name

ser3.name = 'Country_PhoneNumber'
ser3.index.name = 'Country_Name'
ser3
..
..
Country_Name
Korea      82
America     1
Swiss      41
Italy      39
Japan      81
China      86
Rusia       7
Name: Country_PhoneNumber, dtype: int64

DataFrame

data = {'Region' : ['Korea', 'America', 'Chaina', 'Canada', 'Italy'],
        'Sales' : [300, 200, 500, 150, 50],
        'Amount' : [90, 80, 100, 30, 10],
        'Employee' : [20, 10, 30, 5, 3]
        }
s = pd.Series(data)
s
..
..
Region      [Korea, America, Chaina, Canada, Italy]
Sales                      [300, 200, 500, 150, 50]
Amount                        [90, 80, 100, 30, 10]
Employee                         [20, 10, 30, 5, 3]
dtype: object

s = pd.DataFrame(data)
s
..
..
Region	Sales	Amount	Employee
0	Korea	300	90	20
1	America	200	80	10
2	Chaina	500	100	30
3	Canada	150	30	5
4	Italy	50	10	3

s.columns
..
..
Index(['Region', 'Sales', 'Amount', 'Employee'], dtype='object')

s.index
..
..
RangeIndex(start=0, stop=5, step=1)

s.index=['one','two','three','four','five']
s.columns = ['a','b','c','d']
s
..
..
a	b	c	d
one	Korea	300	90	20
two	America	200	80	10
three	Chaina	500	100	30
four	Canada	150	30	5
five	Italy	50	10	3

구조화된 데이터의 표현법

image

pandas와 함께 EDA 시작하기

통계데이터를 활용해서 데이터의 대푯값과 분산을 구하는 것은 EDA(Exploratory Data Analysis)의 기본이라고 할 수 있습니다.

csv

import pandas as pd
import os

csv_path = os.getenv("HOME") + "/aiffel/data_represent/data/covid19_italy_region.csv"
data = pd.read_csv(csv_path)
data
..
..

SNo	Date	Country	RegionCode	RegionName	Latitude	Longitude	HospitalizedPatients	IntensiveCarePatients	TotalHospitalizedPatients	HomeConfinement	CurrentPositiveCases	NewPositiveCases	Recovered	Deaths	TotalPositiveCases	TestsPerformed
0	0	2020-02-24T18:00:00	ITA	13	Abruzzo	42.351222	13.398438	0	0	0	0	0	0	0	0	0	5
1	1	2020-02-24T18:00:00	ITA	17	Basilicata	40.639471	15.805148	0	0	0	0	0	0	0	0	0	0
2	2	2020-02-24T18:00:00	ITA	4	P.A. Bolzano	46.499335	11.356624	0	0	0	0	0	0	0	0	0	1
3	3	2020-02-24T18:00:00	ITA	18	Calabria	38.905976	16.594402	0	0	0	0	0	0	0	0	0	1
4	4	2020-02-24T18:00:00	ITA	15	Campania	40.839566	14.250850	0	0	0	0	0	0	0	0	0	10
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
793	793	2020-04-01T17:00:00	ITA	9	Toscana	43.769231	11.255889	1120	297	1417	3015	4432	259	182	253	4867	36575
794	794	2020-04-01T17:00:00	ITA	4	P.A. Trento	46.068935	11.121231	345	76	421	1062	1483	124	214	173	1870	7675
795	795	2020-04-01T17:00:00	ITA	10	Umbria	43.106758	12.388247	173	45	218	646	864	17	194	37	1095	9080
796	796	2020-04-01T17:00:00	ITA	2	Valle d'Aosta	45.737503	7.320149	85	27	112	428	540	3	32	59	631	1717
797	797	2020-04-01T17:00:00	ITA	5	Veneto	45.434905	12.338452	1718	350	2068	6156	8224	470	902	499	9625	112746
798 rows × 17 columns
data.head()

image

data.tail()

image

data.head(3)

image

data.columns
..
..
Index(['SNo', 'Date', 'Country', 'RegionCode', 'RegionName', 'Latitude',
       'Longitude', 'HospitalizedPatients', 'IntensiveCarePatients',
       'TotalHospitalizedPatients', 'HomeConfinement', 'CurrentPositiveCases',
       'NewPositiveCases', 'Recovered', 'Deaths', 'TotalPositiveCases',
       'TestsPerformed'],
      dtype='object')

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 798 entries, 0 to 797
Data columns (total 17 columns):
 #   Column                     Non-Null Count  Dtype  
---  ------                     --------------  -----  
 0   SNo                        798 non-null    int64  
 1   Date                       798 non-null    object 
 2   Country                    798 non-null    object 
 3   RegionCode                 798 non-null    int64  
 4   RegionName                 798 non-null    object 
 5   Latitude                   798 non-null    float64
 6   Longitude                  798 non-null    float64
 7   HospitalizedPatients       798 non-null    int64  
 8   IntensiveCarePatients      798 non-null    int64  
 9   TotalHospitalizedPatients  798 non-null    int64  
 10  HomeConfinement            798 non-null    int64  
 11  CurrentPositiveCases       798 non-null    int64  
 12  NewPositiveCases           798 non-null    int64  
 13  Recovered                  798 non-null    int64  
 14  Deaths                     798 non-null    int64  
 15  TotalPositiveCases         798 non-null    int64  
 16  TestsPerformed             798 non-null    int64  
dtypes: float64(2), int64(12), object(3)
memory usage: 106.1+ KB
data.describe()

image

data.isnull().sum()
..
..
SNo                          0
Date                         0
Country                      0
RegionCode                   0
RegionName                   0
Latitude                     0
Longitude                    0
HospitalizedPatients         0
IntensiveCarePatients        0
TotalHospitalizedPatients    0
HomeConfinement              0
CurrentPositiveCases         0
NewPositiveCases             0
Recovered                    0
Deaths                       0
TotalPositiveCases           0
TestsPerformed               0
dtype: int64

data['RegionName'].value_counts()
..
..
Valle d'Aosta            38
P.A. Trento              38
Piemonte                 38
Basilicata               38
Umbria                   38
Sicilia                  38
Veneto                   38
Molise                   38
P.A. Bolzano             38
Abruzzo                  38
Calabria                 38
Sardegna                 38
Lombardia                38
Marche                   38
Campania                 38
Friuli Venezia Giulia    38
Lazio                    38
Liguria                  38
Toscana                  38
Emilia-Romagna           38
Puglia                   38
Name: RegionName, dtype: int64

data['Country'].value_counts()
..
..
ITA    798
Name: Country, dtype: int64

data['RegionName'].value_counts().sum()
..
..
798

data['Country'].value_counts().sum()
..
..
798

print(data['TotalPositiveCases'].sum())
print(data['TestsPerformed'].sum())
print(data['Deaths'].sum())
print(data['Recovered'].sum())
..
..
1323913
6329867
129817
164154

data.sum()
..
..
SNo                                                                     318003
Date                         2020-02-24T18:00:002020-02-24T18:00:002020-02-...
Country                      ITAITAITAITAITAITAITAITAITAITAITAITAITAITAITAI...
RegionCode                                                                8132
RegionName                   AbruzzoBasilicataP.A. BolzanoCalabriaCampaniaE...
Latitude                                                          34350.941591
Longitude                                                          9756.312476
HospitalizedPatients                                                    425381
IntensiveCarePatients                                                    65912
TotalHospitalizedPatients                                               491293
HomeConfinement                                                         538649
CurrentPositiveCases                                                   1029942
NewPositiveCases                                                        110566
Recovered                                                               164154
Deaths                                                                  129817
TotalPositiveCases                                                     1323913
TestsPerformed                                                         6329867
dtype: object

print(data['TestsPerformed'].corr(data['TotalPositiveCases']))
print(data['TestsPerformed'].corr(data['Deaths']))
print(data['TotalPositiveCases'].corr(data['Deaths']))

data.corr()
..
..
0.8555291657820235
0.7612209669865387
0.975268668316802

image

data.drop(['Latitude','Longitude','Country','Date','HospitalizedPatients',  'IntensiveCarePatients', 'TotalHospitalizedPatients','HomeConfinement','RegionCode','SNo'], axis=1, inplace=True)

data.corr()

image

pandas 통계 관련 메소드

이상으로 pandas에서 제공하는 통계 관련 메소드를 정리했으니 한번 확인해 보세요.

  • count(): NA를 제외한 수를 반환합니다.

  • describe(): 요약통계를 계산합니다.

  • min(), max(): 최소, 최댓값을 계산합니다.

  • sum(): 합을 계산합니다.

  • mean(): 평균을 계산합니다.

  • median(): 중앙값을 계산합니다.

  • var(): 분산을 계산합니다.

  • std(): 표준편차를 계산합니다.

  • argmin(), argmax(): 최소, 최댓값을 가지고 있는 값을 반환 합니다.

  • idxmin(), idxmax(): 최소, 최댓값을 가지고 있는 인덱스를 반환합니다.

  • cumsum(): 누적 합을 계산합니다.

  • pct_change(): 퍼센트 변화율을 계산합니다.

Leave a comment