Rev Notebook

[현대사회의 데이터와 통계학] 1. NumPy : 배열 생성하기

by Rev_

1) 시퀀스 데이터로부터 배열 생성

  • 간단한 리스트 만들기
data1 = [0, 1, 2, 3, 4, 5]
data1

실행 결과 : [0, 1, 2, 3, 4, 5]

위처럼 data1이라는 리스트가 만들어진다.

 

data1[-1]

위 리스트의 인덱스는 0, 1, 2..., 5 로 진행되지만, 역순으로 진행할땐 -1, -2, -3,..., -6 이 된다.

따라서 위의 결과는 5 이다.

 

a1 = np.array(data1)

data1 이라는 리스트를 NumPy 배열로 생성하였다.

a1을 실행한다면 array([0, 1, 2, 3, 4, 5]) 가 결과로 나오게 된다.

또한 a1의 데이터타입은 numpy.ndarray로 나타난다.

데이터타입은 type(a1) 으로 확인할 수 있다.

 

data2 = [0.1, 5, 4, 12, 0.5]
a2 = np.array(data2)

하나의 리스트에 여러 정수와 실수가 섞여 있다면 모두 실수형으로 저장된다.

그러므로 a1의 자료형은 int32이고, a2의 자료형은 float64로 나타난다.

각각의 자료형은 a1.dtype 으로 확인할 수 있다.

 

data3 = (0.1, 5, 4, 12, 0.5)
a3 = np.array(data3)

튜플 또한 NumPy 배열로 만들 수 있다.

  • 리스트와 튜플의 차이 ? 리스트[]는 변경가능하고, 튜플()은 변경할 수 없다.
  • 데이터를 리스트나 튜플 타입으로 두지 않고 배열로 바꾸는 이유 ? 비교적 빠른 연산을 지원하고 메모리를 효율적으로 사용이다.

 

np.array([0.5, 2, 0.01, 8])

미리 리스트(튜플)을 만들지 않고 바로 array() 의 인자로 리스트(튜플)을 사용할 수 있다.

 

np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
s1 = np.array(['a', 'b', 'c'])
s2 = np.array(['12', '9.5', '0.8'])

중첩 리스트, 문자로도 배열을 만들 수 있다.

s1은 dtype이 '<U1'로 나타나고, s2는 dtype이 '<U3'로 나타나는데 s1은 하나의 문자로 이루어져있고 s2는 소수점까지 최대 3개의 입력으로 이루어져있기 때문인듯 하다.

+ U는 유니코드 문자열이라는 의미

s3 = [19.7, 'abc', 0, '1.5']
s4 = np.array(s3)
  • 정수, 실수, 문자열이 섞여있는 배열의 dtype은? 문자열 타입의 배열이 된다. dtype() 의 결과는 dtype('<U32') 이고 즉, 유니코드 문자열이라는 것이다.

 

2) 범위를 지정해서 배열 생성하기

  • arange()

np.arange(start, end, step) 함수는 범위와 간격을 지정해서 배열을 만든다.

start의 기본값은 0, step의 기본값은 1이다. (생략가능)

range() 와의 차이는 range()는 정수만 만들 수 있지만 arange()는 실수도 가능하다.

aa = np.arange(0, 10, 2)

0부터 10미만까지 2씩 증가하는 배열 생성

-> [0, 2, 4, 6, 8]

 

bb = list(range(0, 10, 2))

위와 동일하지만 리스트 생성

-> [0, 2, 4, 6, 8]

 

  • aa와 bb 데이터의 연산
aa + bb

-> [0, 4, 8, 12, 16]

bb + bb

-> [0, 2, 4, 6, 8, 0, 2, 4, 6, 8]

같은 길이의 배열끼리, 또는 배열과 리스트를 더하면 같은 위치의 값끼리 더한 동일한 길이의 배열이 생긴다.

하지만 리스트끼리 더하면 리스트를 이어붙이게 된다. (곱셈도 덧셈과 똑같음)

+ 배열에 대해서는 데이터타입이 있지만 리스트에 대해서는 데이터타입이 없다.

배열은 모두 동일한 데이터 타입으로 만들어져 들어가지만 리스트에는 여러가지 데이터타입이 있을 수 있다.

 

  • reshape() : reshape(m,n)을 이용해서 1차원 배열을 m X n 2차원 배열로 만들 수 있다.
num = np.arange(12)

0에서 11까지의 원소를 가지고 있는 배열이 생성된다.

차원을 알려면 num.ndim 코드를 사용하면 된다. 현재 num은 1차원이다.

 

num.reshape(4, 3)

4행 3열로 된 2차원 배열로 만들어주었다.

array([[0, 1, 2],

      [3, 4, 5],

      [6, 7, 8]

      [9, 10, 11]])

 

물론, 기존 일차원 배열의 원소 개수와 m X n 원소의 개수가 같아야 한다.

 

  • shape : 배열의 각 차원의 크기를 알아보려면 배열이름 뒤에 shape를 붙이면 된다.
b1 = np.arange(12).reshape(4, 3)
b1.shape

원소가 0에서 11까지인 배열을 4X3 행렬로 reshape 하였다.

결과는 (4, 3)으로 출력된다.

튜플을 보여주게 되는데 (행의 개수, 열의 개수) 의 형식이다.

 

1차원인 배열은 (12, ) 와 같이 표현된다.

 

a1 = np.arange(10)
a1.shape = (5, 2)

그러하여 reshape를 이용해서도 2차원 배열을 만들 수 있다.

array([[0, 1],

      [2, 3],

      [4, 5],

      [6, 7],

      [8, 9]])

 

b3 = np.arange(24).reshape(2, 3, 4)

3차원 배열 또한 만들 수 있다.

array([[0, 1, 2, 3],

      [4, 5, 6, 7],

      [8, 9, 10, 11]],

 

      [[12, 13, 14, 15],

      [16, 17, 18, 19],

      [20, 21, 22, 23]])

=> 3 X 4 행렬 두개로 이루어진 3차원 배열

 

  • 배열의 연결, 분리 (concatenate())
x1 = np.array([1, 2, 3])
x2 = np.array([9, 8, 7])
x3 = np.array([3, 6, 9])
np.concatenate([x1, x2, x3])

array([1, 2, 3, 9, 8, 7, 3, 6, 9])

concatenate 함수는 매우 유용하게 쓰이는 것 중 하나이며, Numpy 배열들을 하나로 합치는데 이용된다.

 

y1 = np.array([[1, 2, 3], [4, 5, 6]])
y2 = np.array([[9, 7, 2], [0,  3,  5], [7,  9, 1]])
np.concatenate([y1, y2])

array([[1, 2, 3],

      [4, 5, 6],

      [9, 7, 2],

      [0, 3, 5],

      [7, 9, 1]])

 

np.concatenate([y1, y2[:2]], axis = 0) # 행 방향으로 연결

array([[1, 2, 3],

      [4, 5, 6],

      [9, 7, 2],

      [0, 3, 5]])

 

np.concatenate([y1, y2[:2]], axis = 1) # 열 방향으로 연결

array([[1, 2, 3, 9, 7, 2],

      [4, 5, 6, 0, 3, 5]])

 

  • vstack, hstack
np.vstack([y1, y2])

array([[1, 2, 3],

      [4, 5, 6],

      [9, 7, 2],

      [0, 3, 5],

      [7, 9, 1]])

=> 행 방향으로 연결한다.

np.concatenate([y1, y2], axis = 0)과 동일함

vstack을 사용할 때는 열 개수가 일치해야 한다.

 

np.hstack([y1, y2[1:]])

array([[1, 2, 3, 0, 3, 5],

      [4, 5, 6, 7, 9, 1]])

=> 열 방향으로 연결한다.

hstack을 사용하는 경우에는 배열 행이 일치해야 한다.

 

  • linspace()
np.linspace(1, 10, 15)

np.linspace()는 start부터 stop까지 같은 간격으로 num개의 숫자로 이루어진 배열을 만든다.

np.linspace(start, stop, num)의 형식인데, num의 기본값은 50이다.

 

3) 특별한 형태의 배열 생성

: zeros(), ones(), full(), eye() 등이 있음

 

np.zeros(10, dtype='i')

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32)

=> 0을 10개 갖는 배열 생성

데이터타입을 int로 설정하면 정수값을 가질 수 있음

 

np.ones(5)

array([1., 1., 1., 1., 1.])

=> 1을 5개 갖는 배열 생성

 

np.full((3, 4), 'Data Science')

array([['Data Science', 'Data Science', 'Data Science', 'Data Science'],

        ['Data Science', 'Data Science', 'Data Science', 'Data Science'],

        ['Data Science', 'Data Science', 'Data Science', 'Data Science']],

        dtype='<U12')

=> 지정한 수의 배열을 동일한 값으로 채움

 

np.eye(4)

array([[1., 0., 0., 0.],

        [0., 1., 0., 0.],

        [0., 0., 1., 0.],

        [0., 0., 0., 1.]])

=> 대각선 원소가 1인 n X n 항등행렬을 만들어 줌

 

4) 배열의 데이터 타입 변환

str_a2 = np.array(['1', '3', '5', '7', '9'])
num_a2 = str_a2.astype(int)
num_a2

astype()로 데이터타입을 변환할 수 있음

실수의 데이터를 int로 변환하면 소수점 아래를 버림 하여 표현한다 (4.57 -> 4)

 

  • 대각행렬
np.eye(8)

대각선 원소가 모두 1인 대각행렬이다. 이는 항등행렬이라고 불린다.

 

a = np.eye(5) * 3
a.astype(int)

=> 대각선 원소가 모두 정수 3인 5X5 대각행렬

 

np.diag([3, 3, 3, 3, 3])

=> 대각선 원소가 모두 정수 3인 5X5 대각행렬

함수 diag()는 대각행렬을 만든다.

 

5) 난수 배열의 생성

np.random.rand()

=> 0과 1사이의 난수를 한 개 뽑음

 

np.random.rand(10)

=> 0과 1사이의 난수를 10개 뽑음

 

np.random.rand(2, 3)

=> 0과 1사이의 난수를 뽑아 2X3 배열 만들기

3차원 배열 또한 만들 수 있음 !

 

np.random.randint(10, size=(3, 4))

=> 10미만의 난수를 뽑아 3X4 배열 만들기

 

np.random.randint(1, 30)

=> 1과 30사이에서 정수 난수 하나 뽑기

 

np.random.randint(1, 30, (4, 5))

=> 1과 30사이에서 정수 난수를 뽑아 4X5 배열 만들기

 

np.random.randint(100)

=> 100미만의 랜덤 숫자 하나 뽑기

 

np.random.seed(99)
np.random.randint(1, 100, (5,))

=> np.random.seed()는 난수를 예측 가능 하도록 함

위의 코드를 출력하면 항상 동일한 난수가 출력된다.

 

np.random.randn(10)

=> 표준정규분포 난수 10개 만들기

블로그의 정보

Hi Rev

Rev_

활동하기