LLM(Large Language Model)의 기초/데이터 분석

1. 넘파이(Numpy)

인공지능파이썬 2024. 12. 16. 12:13

1. 넘파이(Numpy)

* 넘파이(Numpy)는 파이썬에서 사용되는 과학 및 수학 연산을 위한 강력한 라이브러리입니다. 
* 주로 다차원 배열을 다루는 데에 특화되어 있어, 데이터 분석, 머신러닝, 과학 계산 등 다양한 분야에서 널리 사용됩니다. 
* 넘파이 배열은 C 언어로 구현되어 있어 연산이 빠르고 효율적입니다. 
* 특히 큰 데이터셋에서 수치 연산을 수행할 때 뛰어난 성능을 보입니다.
* 또한 메모리 사용을 최적화하고 효율적으로 관리합니다.

# 설치
pip install numpy

 
1-1) numpy를 import 해주면 된다.

import numpy as np

 
2. 넘파이의 주요 특징과 기능
 
2-1. 다차원 배열(N-dimensional array)
* 넘파이의 핵심은 다차원 배열인 ndarray입니다. 
* ndarray는 동일한 자료형을 가지는 원소들로 이루어져 있습니다. 
* 다차원 배열은 1차원, 2차원, 3차원 등 다양한 차원을 가질 수 있습니다.
 
예시 1)

# 리스트(list) 생성
list1 = [1, 2, 3, 4]  # list1이라는 이름의 리스트에 [1, 2, 3, 4]라는 4개의 정수 요소가 들어 있음

# 리스트 출력
print(list1)  # 출력: [1, 2, 3, 4] -> list1에 저장된 리스트 전체를 출력

# 리스트의 자료형 확인
print(type(list1))  # 출력: <class 'list'> -> list1은 리스트(list) 자료형임을 나타냄

# 리스트의 첫 번째 요소 출력
print(list1[0])  # 출력: 1 -> list1의 첫 번째 요소(인덱스 0)에 해당하는 값을 출력

# 첫 번째 요소의 자료형 확인
print(type(list1[0]))  # 출력: <class 'int'> -> 첫 번째 요소는 정수(int) 자료형임을 나타냄

 
예시 2)

# 이중 리스트(list) 생성
list2 = [[1, 2, 3, 4], [5, 6, 7, 8]]  
# list2라는 이름의 리스트에 2개의 하위 리스트가 포함되어 있음: 
# 첫 번째 하위 리스트는 [1, 2, 3, 4], 두 번째 하위 리스트는 [5, 6, 7, 8]

# 이중 리스트 출력
print(list2)  
# 출력: [[1, 2, 3, 4], [5, 6, 7, 8]] 
# list2에 저장된 이중 리스트 전체를 출력함

# list2의 자료형 확인
print(type(list2))  
# 출력: <class 'list'>  
# list2는 리스트 자료형임을 나타냄

# list2의 첫 번째 요소(하위 리스트)의 자료형 확인
print(type(list2[0]))  
# 출력: <class 'list'>  
# list2의 첫 번째 요소는 [1, 2, 3, 4]라는 하위 리스트이며, 이 하위 리스트도 리스트 자료형임

 
예시 3)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성
ndarr1 = np.array([1, 2, 3, 4])  
# ndarr1이라는 이름의 NumPy 배열에 [1, 2, 3, 4]라는 정수 요소들이 포함됨

# NumPy 배열 출력
print(ndarr1)  
# 출력: [1 2 3 4]  
# ndarr1에 저장된 NumPy 배열을 출력함. 일반 리스트와 달리 쉼표(,) 없이 출력됨

# ndarr1의 자료형 확인
print(type(ndarr1))  
# 출력: <class 'numpy.ndarray'>  
# ndarr1은 NumPy에서 제공하는 다차원 배열(ndarray) 자료형임을 나타냄

# ndarr1의 첫 번째 요소의 자료형 확인
print(type(ndarr1[0]))  
# 출력: <class 'numpy.int64'>  
# ndarr1의 첫 번째 요소는 NumPy의 정수 자료형(numpy.int64)임을 나타냄

 

예시 4)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열(ndarray) 생성
ndarr2 = np.array([[1, 2, 3], [4, 5, 6]])
# ndarr2는 2개의 하위 리스트(또는 행)를 가지는 2차원 NumPy 배열입니다.
# 첫 번째 행: [1, 2, 3]
# 두 번째 행: [4, 5, 6]

# NumPy 배열 출력
print(ndarr2)  
# 출력: 
# [[1 2 3]
#  [4 5 6]]
# 2차원 NumPy 배열이 행(row)과 열(column) 형태로 출력됩니다.

# ndarr2의 자료형 확인
print(type(ndarr2))  
# 출력: <class 'numpy.ndarray'>  
# ndarr2는 NumPy에서 제공하는 다차원 배열(ndarray) 자료형임을 나타냅니다.

# ndarr2의 첫 번째 요소(첫 번째 행)의 자료형 확인
print(type(ndarr2[0]))  
# 출력: <class 'numpy.ndarray'>  
# ndarr2[0]은 ndarr2의 첫 번째 행인 [1, 2, 3]이며, 이 또한 NumPy 배열(ndarray)입니다.

 
2-2. 리스트와 ndarray 변환
* 데이터 타입을 다른 데이터 타입으로 변환할 수 있습니다. 
* 리스트에서 배열로의 변환은 np.array() 함수를 사용하고, 배열에서 리스트로의 변환은 tolist() 메서드를 사용합니다.
 
예시 1)

import numpy as np  # NumPy 라이브러리를 가져옴

# 일반 Python 리스트 생성
list1 = [1, 2, 3, 4]  
# list1은 [1, 2, 3, 4]라는 정수 요소들을 포함하는 Python 리스트입니다.

# Python 리스트를 NumPy 배열로 변환
ndarr1 = np.array(list1)  
# list1을 NumPy 배열(ndarray)로 변환하여 ndarr1에 저장합니다.

# NumPy 배열 출력
print(ndarr1)  
# 출력: [1 2 3 4]  
# NumPy 배열이 생성되었으며, 리스트와 달리 쉼표(,) 없이 출력됩니다.

# ndarr1의 자료형 확인
print(type(ndarr1))  
# 출력: <class 'numpy.ndarray'>  
# ndarr1은 NumPy의 다차원 배열 객체인 `numpy.ndarray`임을 나타냅니다.

 
예시 2)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열 생성
ndarr1 = np.array([1, 2, 3, 4])  
# ndarr1은 [1, 2, 3, 4]라는 정수 요소를 포함하는 NumPy 배열입니다.

# NumPy 배열을 Python 리스트로 변환
list2 = ndarr1.tolist()  
# ndarr1을 Python 리스트로 변환하여 list2에 저장합니다.

# Python 리스트 출력
print(list2)  
# 출력: [1, 2, 3, 4]  
# NumPy 배열이 Python 리스트로 변환되어 출력됩니다.

# list2의 자료형 확인
print(type(list2))  
# 출력: <class 'list'>  
# list2는 Python의 리스트 자료형임을 나타냅니다.

 
2-3. ndarray의 데이터 타입
* 넘파이의 ndarray는 동일한 자료형을 가지는 원소들로 이루어져 있으며, 다양한 데이터 타입을 지원합니다.
 
예시 1)

# 다양한 자료형을 포함하는 Python 리스트 생성
list1 = [1, 3.14, 'Python', '😊', True]
# list1은 5개의 요소를 포함하며, 각 요소는 서로 다른 자료형입니다.
# 요소:
# 1 - 정수 (int)
# 3.14 - 실수 (float)
# 'Python' - 문자열 (str)
# '😊' - 문자열 (str, 이모지)
# True - 불리언 (bool)

# 리스트 출력
print(list1)
# 출력: [1, 3.14, 'Python', '😊', True]
# 리스트 전체가 출력됩니다.

# 리스트의 자료형 확인
print(type(list1))
# 출력: <class 'list'>
# list1은 Python의 리스트 자료형임을 나타냅니다.

# 리스트의 각 요소의 자료형 확인
print(type(list1[0]))
# 출력: <class 'int'>
# list1[0]은 정수 1이므로 자료형은 int입니다.

print(type(list1[1]))
# 출력: <class 'float'>
# list1[1]은 실수 3.14이므로 자료형은 float입니다.

print(type(list1[2]))
# 출력: <class 'str'>
# list1[2]는 문자열 'Python'이므로 자료형은 str입니다.

print(type(list1[3]))
# 출력: <class 'str'>
# list1[3]은 문자열 '😊' (이모지)로, 자료형은 str입니다.

print(type(list1[4]))
# 출력: <class 'bool'>
# list1[4]는 불리언 값 True이므로 자료형은 bool입니다.

 
예시 2)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성
ndarr1 = np.array([1, 2, 3, 4])  
# ndarr1은 [1, 2, 3, 4]라는 정수 요소를 포함하는 NumPy 배열입니다.

# NumPy 배열 출력
print(ndarr1)  
# 출력: [1 2 3 4]  
# NumPy 배열이 쉼표 없이 출력됩니다.

# ndarr1의 자료형 확인
print(type(ndarr1))  
# 출력: <class 'numpy.ndarray'>  
# ndarr1은 NumPy에서 제공하는 다차원 배열 객체(ndarray)임을 나타냅니다.

# ndarr1의 첫 번째 요소의 자료형 확인
print(type(ndarr1[0]))  
# 출력: <class 'numpy.int64'>  
# ndarr1[0]은 NumPy 배열의 첫 번째 요소이며, 정수 자료형이 numpy.int64입니다.

# ndarr1의 두 번째 요소의 자료형 확인
print(type(ndarr1[1]))  
# 출력: <class 'numpy.int64'>  
# ndarr1[1]도 numpy.int64 자료형입니다.

# ndarr1의 세 번째 요소의 자료형 확인
print(type(ndarr1[2]))  
# 출력: <class 'numpy.int64'>  
# ndarr1[2]도 numpy.int64 자료형입니다.

# ndarr1의 네 번째 요소의 자료형 확인
print(type(ndarr1[3]))  
# 출력: <class 'numpy.int64'>  
# ndarr1[3]도 numpy.int64 자료형입니다.

 
예시 3)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성
ndarr2 = np.array([1, 2, 3.14, 4])  
# ndarr2는 [1, 2, 3.14, 4]라는 요소를 포함하는 NumPy 배열입니다.
# 이 중 하나의 요소(3.14)가 실수(float)여서, 배열 전체가 실수(float)로 변환됩니다.

# NumPy 배열 출력
print(ndarr2)  
# 출력: [1.   2.   3.14 4.  ]  
# 모든 요소가 실수(float)로 변환되어 소수점 형태로 출력됩니다.

# ndarr2의 자료형 확인
print(type(ndarr2))  
# 출력: <class 'numpy.ndarray'>  
# ndarr2는 NumPy에서 제공하는 다차원 배열 객체(ndarray)임을 나타냅니다.

# ndarr2의 첫 번째 요소의 자료형 확인
print(type(ndarr2[0]))  
# 출력: <class 'numpy.float64'>  
# ndarr2[0]은 1이지만, 배열 전체가 실수(float)로 변환되었기 때문에 numpy.float64입니다.

# ndarr2의 두 번째 요소의 자료형 확인
print(type(ndarr2[1]))  
# 출력: <class 'numpy.float64'>  
# ndarr2[1]도 실수로 변환되었기 때문에 numpy.float64입니다.

# ndarr2의 세 번째 요소의 자료형 확인
print(type(ndarr2[2]))  
# 출력: <class 'numpy.float64'>  
# ndarr2[2]는 원래 실수 3.14이므로 numpy.float64입니다.

# ndarr2의 네 번째 요소의 자료형 확인
print(type(ndarr2[3]))  
# 출력: <class 'numpy.float64'>  
# ndarr2[3]도 실수로 변환되었기 때문에 numpy.float64입니다.

 
예시 4)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성
ndarr3 = np.array([1, 2, 3.14, True])
# ndarr3는 [1, 2, 3.14, True]라는 요소를 포함하는 NumPy 배열입니다.
# 이 중 하나의 요소(3.14)가 실수(float)이기 때문에, 배열 전체가 실수(float)로 변환됩니다.

# NumPy 배열 출력
print(ndarr3)
# 출력: [1.   2.   3.14 1.  ]
# 모든 요소가 실수(float)로 변환되어 소수점이 붙은 형태로 출력됩니다.
# True는 1로 변환되었고, 실수형(float)으로 표시됩니다.

# ndarr3의 자료형 확인
print(type(ndarr3))
# 출력: <class 'numpy.ndarray'>
# ndarr3는 NumPy에서 제공하는 다차원 배열 객체(ndarray)입니다.

# ndarr3의 첫 번째 요소의 자료형 확인
print(type(ndarr3[0]))
# 출력: <class 'numpy.float64'>
# ndarr3[0]은 정수 1이었지만, 실수형(float)으로 변환되어 numpy.float64입니다.

# ndarr3의 두 번째 요소의 자료형 확인
print(type(ndarr3[1]))
# 출력: <class 'numpy.float64'>
# ndarr3[1]도 정수 2였지만, 실수형(float)으로 변환되어 numpy.float64입니다.

# ndarr3의 세 번째 요소의 자료형 확인
print(type(ndarr3[2]))
# 출력: <class 'numpy.float64'>
# ndarr3[2]는 원래 실수 3.14였으므로 numpy.float64입니다.

# ndarr3의 네 번째 요소의 자료형 확인
print(type(ndarr3[3]))
# 출력: <class 'numpy.float64'>
# ndarr3[3]은 불리언 값 True였지만, 1로 변환되고 실수형(float)으로 표시되므로 numpy.float64입니다.

 
예시 5)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성
ndarr4 = np.array(['1', 2, 3.14, True])
# ndarr4는 ['1', 2, 3.14, True]라는 요소를 포함하는 NumPy 배열입니다.
# 이 중 하나의 요소('1')가 문자열(str)이기 때문에, 배열 전체의 요소가 문자열(str)로 변환됩니다.

# NumPy 배열 출력
print(ndarr4)
# 출력: ['1' '2' '3.14' 'True']
# 모든 요소가 문자열로 변환되어 출력됩니다.

# ndarr4의 자료형 확인
print(type(ndarr4))
# 출력: <class 'numpy.ndarray'>
# ndarr4는 NumPy에서 제공하는 다차원 배열 객체(ndarray)입니다.

# ndarr4의 첫 번째 요소의 자료형 확인
print(type(ndarr4[0]))
# 출력: <class 'numpy.str_'>
# ndarr4[0]은 문자열 '1'이며, NumPy 배열에서는 numpy.str_ 자료형입니다.

# ndarr4의 두 번째 요소의 자료형 확인
print(type(ndarr4[1]))
# 출력: <class 'numpy.str_'>
# ndarr4[1]은 정수 2였지만, 문자열로 변환되어 numpy.str_입니다.

# ndarr4의 세 번째 요소의 자료형 확인
print(type(ndarr4[2]))
# 출력: <class 'numpy.str_'>
# ndarr4[2]는 실수 3.14였지만, 문자열로 변환되어 numpy.str_입니다.

# ndarr4의 네 번째 요소의 자료형 확인
print(type(ndarr4[3]))
# 출력: <class 'numpy.str_'>
# ndarr4[3]은 불리언 True였지만, 문자열로 변환되어 numpy.str_입니다.

 
예시 6)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성 (dtype을 int로 지정)
ndarr3 = np.array([1, 2, 3.14, True], dtype=int)  
# 리스트 [1, 2, 3.14, True]를 NumPy 배열로 변환하며, 모든 요소를 정수(int)로 변환하도록 지정했습니다.
# 실수 3.14는 정수로 변환되어 3이 되고, True는 정수 1로 변환됩니다.

# NumPy 배열 출력
print(ndarr3)
# 출력: [1 2 3 1]  
# 모든 요소가 정수형(int)으로 변환되어 출력됩니다.

# ndarr3의 자료형 확인
print(type(ndarr3))
# 출력: <class 'numpy.ndarray'>
# ndarr3는 NumPy에서 제공하는 다차원 배열 객체(ndarray)입니다.

# ndarr3의 첫 번째 요소의 자료형 확인
print(type(ndarr3[0]))
# 출력: <class 'numpy.int64'>
# ndarr3[0]은 정수 1이며, 자료형은 numpy.int64입니다.

# ndarr3의 두 번째 요소의 자료형 확인
print(type(ndarr3[1]))
# 출력: <class 'numpy.int64'>
# ndarr3[1]은 정수 2이며, 자료형은 numpy.int64입니다.

# ndarr3의 세 번째 요소의 자료형 확인
print(type(ndarr3[2]))
# 출력: <class 'numpy.int64'>
# ndarr3[2]는 실수 3.14가 정수로 변환된 값 3이며, 자료형은 numpy.int64입니다.

# ndarr3의 네 번째 요소의 자료형 확인
print(type(ndarr3[3]))
# 출력: <class 'numpy.int64'>
# ndarr3[3]은 불리언 값 True가 정수 1로 변환된 값이며, 자료형은 numpy.int64입니다.

 
예시 7)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열(ndarray) 생성 (dtype을 int로 지정)
ndarr4 = np.array(['1', 2, 3.14, True], dtype=int)
# 리스트 ['1', 2, 3.14, True]를 NumPy 배열로 변환하며, 모든 요소를 정수(int)로 변환하도록 지정했습니다.
# 문자열 '1'은 정수 1로 변환됩니다.
# 실수 3.14는 정수로 변환되어 3이 됩니다.
# 불리언 True는 정수 1로 변환됩니다.

# NumPy 배열 출력
print(ndarr4)
# 출력: [1 2 3 1]
# 모든 요소가 정수형(int)으로 변환되어 출력됩니다.

# ndarr4의 자료형 확인
print(type(ndarr4))
# 출력: <class 'numpy.ndarray'>
# ndarr4는 NumPy에서 제공하는 다차원 배열 객체(ndarray)입니다.

# ndarr4의 첫 번째 요소의 자료형 확인
print(type(ndarr4[0]))
# 출력: <class 'numpy.int64'>
# ndarr4[0]은 '1'이 정수 1로 변환되었으므로 numpy.int64입니다.

# ndarr4의 두 번째 요소의 자료형 확인
print(type(ndarr4[1]))
# 출력: <class 'numpy.int64'>
# ndarr4[1]은 정수 2이므로 numpy.int64입니다.

# ndarr4의 세 번째 요소의 자료형 확인
print(type(ndarr4[2]))
# 출력: <class 'numpy.int64'>
# ndarr4[2]는 실수 3.14가 정수로 변환되어 3이 되었으므로 numpy.int64입니다.

# ndarr4의 네 번째 요소의 자료형 확인
print(type(ndarr4[3]))
# 출력: <class 'numpy.int64'>
# ndarr4[3]은 불리언 True가 정수 1로 변환되었으므로 numpy.int64입니다.

 
2-4. ndarray 인덱싱과 슬라이싱
넘파이의 ndarray는 리스트와 유사하게 인덱싱과 슬라이싱을 지원합니다.
 
예시 1)

import numpy as np  # NumPy 라이브러리를 가져옴

# 이모지(문자열)를 요소로 가지는 NumPy 배열 생성
ndarr1 = np.array(['🍓', '🍉', '🍌', '🍒', '🍑'])  
# ndarr1은 5개의 이모지 문자열을 포함하는 NumPy 배열입니다.

# NumPy 배열 출력
print(ndarr1)  
# 출력: ['🍓' '🍉' '🍌' '🍒' '🍑']
# 배열에 있는 각 이모지 요소가 출력됩니다. NumPy 배열에서는 쉼표(,) 없이 요소들이 나열됩니다.

# NumPy 배열의 shape(형상) 확인
print(ndarr1.shape)  
# 출력: (5,)
# 배열의 shape은 (5,)로, 1차원 배열이며 총 5개의 요소가 있음을 나타냅니다.

 
예시 2)

import numpy as np  # NumPy 라이브러리를 가져옴

# 이모지(문자열)를 요소로 가지는 NumPy 배열 생성
ndarr1 = np.array(['🍓', '🍉', '🍌', '🍒', '🍑'])
# ndarr1은 ['🍓', '🍉', '🍌', '🍒', '🍑']라는 5개의 이모지 문자열을 포함하는 NumPy 배열입니다.

# 첫 번째 요소 출력 (정방향 인덱싱)
print(ndarr1[0])
# 출력: 🍓
# ndarr1의 첫 번째 요소인 '🍓'를 출력합니다. 인덱스는 0입니다.

# 다섯 번째 요소 출력 (정방향 인덱싱)
print(ndarr1[4])
# 출력: 🍑
# ndarr1의 다섯 번째 요소인 '🍑'를 출력합니다. 인덱스는 4입니다.

# 마지막 요소 출력 (역방향 인덱싱)
print(ndarr1[-1])
# 출력: 🍑
# ndarr1의 마지막 요소인 '🍑'를 출력합니다. 역방향 인덱스는 -1입니다.

# 끝에서 두 번째 요소 출력 (역방향 인덱싱)
print(ndarr1[-2])
# 출력: 🍒
# ndarr1의 끝에서 두 번째 요소인 '🍒'를 출력합니다. 역방향 인덱스는 -2입니다.

 
예시 3)

import numpy as np  # NumPy 라이브러리를 가져옴

# 이모지(문자열)를 요소로 가지는 NumPy 배열 생성
ndarr1 = np.array(['🍓', '🍉', '🍌', '🍒', '🍑'])
# ndarr1은 ['🍓', '🍉', '🍌', '🍒', '🍑']라는 5개의 이모지 문자열을 포함하는 NumPy 배열입니다.

# 1. 인덱스 0부터 2까지 슬라이싱 (0 <= 인덱스 < 3)
print(ndarr1[0:3])
# 출력: ['🍓' '🍉' '🍌']
# ndarr1의 인덱스 0, 1, 2에 해당하는 요소가 출력됩니다.

# 2. 인덱스 2부터 끝까지 슬라이싱
print(ndarr1[2:])
# 출력: ['🍌' '🍒' '🍑']
# ndarr1의 인덱스 2부터 배열의 끝까지의 요소가 출력됩니다.

# 3. 처음부터 인덱스 2까지 슬라이싱 (0 <= 인덱스 < 3)
print(ndarr1[:3])
# 출력: ['🍓' '🍉' '🍌']
# ndarr1의 처음부터 인덱스 2까지의 요소가 출력됩니다.

 
예시 4)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 생성
ndarr2d = np.array([[1, 2, 3, 4],
                    [5, 6, 7, 8],
                    [9, 10, 11, 12]])
# ndarr2d는 3개의 행(row)과 4개의 열(column)을 가지는 2차원 NumPy 배열입니다.
# 배열 요소는 다음과 같이 구성됩니다:
# [[ 1,  2,  3,  4],   # 첫 번째 행
#  [ 5,  6,  7,  8],   # 두 번째 행
#  [ 9, 10, 11, 12]]   # 세 번째 행

# 2차원 NumPy 배열 출력
print(ndarr2d)
# 출력:
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
# 각 행(row)과 열(column)이 배열 형태로 출력됩니다.

# 배열의 shape(형상) 확인
print(ndarr2d.shape)
# 출력: (3, 4)
# 배열의 shape은 (3, 4)로, 3개의 행과 4개의 열이 있음을 나타냅니다.

 
예시 5)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 생성
ndarr2d = np.array([[1, 2, 3, 4],
                    [5, 6, 7, 8],
                    [9, 10, 11, 12]])
# ndarr2d는 3개의 행(row)과 4개의 열(column)을 가지는 2차원 배열입니다.

print(ndarr2d[0, :])
-->
# 출력: [1 2 3 4]
**ndarr2d[0, :]**는 첫 번째 행의 모든 열을 선택합니다.
인덱스 0: 첫 번째 행을 선택합니다.
슬라이싱 :: 해당 행의 모든 열을 선택합니다.
결과: [1 2 3 4]

print(ndarr2d[0,])
-->
# 출력: [1 2 3 4]
**ndarr2d[0,]**는 첫 번째 행을 선택합니다.
콤마(,) 뒤에 아무 내용이 없으면, 해당 행의 모든 열을 선택하는 것과 동일합니다.
결과: [1 2 3 4]
**ndarr2d[0,]**는 **ndarr2d[0, :]**와 동일합니다.

print(ndarr2d[0])
-->
# 출력: [1 2 3 4]
**ndarr2d[0]**는 첫 번째 행을 선택합니다.
열 슬라이싱(:)을 생략하면, 기본적으로 해당 행의 모든 열을 선택합니다.
결과: [1 2 3 4]
**ndarr2d[0]**는 **ndarr2d[0, :]**와 동일합니다.


ndarr2d[0, :]:
첫 번째 행의 모든 열을 선택 → [1 2 3 4]
ndarr2d[0,]:
첫 번째 행의 모든 열을 선택 → [1 2 3 4]
ndarr2d[0]:
첫 번째 행의 모든 열을 선택 → [1 2 3 4]

결과
-->
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]

 
예시 6)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 생성
ndarr2d = np.array([[1, 2, 3, 4],
                    [5, 6, 7, 8],
                    [9, 10, 11, 12]])
# ndarr2d는 3개의 행(row)과 4개의 열(column)을 가지는 2차원 배열입니다.

print(ndarr2d[:, 0])
**ndarr2d[:, 0]**는 모든 행에서 첫 번째 열의 요소를 선택합니다.
콜론(:): 모든 행(row)을 의미합니다.
인덱스 0: 첫 번째 열(column)을 선택합니다.
ndarr2d[0, 0] = 1  → 첫 번째 행, 첫 번째 열
ndarr2d[1, 0] = 5  → 두 번째 행, 첫 번째 열
ndarr2d[2, 0] = 9  → 세 번째 행, 첫 번째 열
-->
[1 5 9]

 
예시 7)

import numpy as np  # NumPy 라이브러리를 가져옴

# 1차원 NumPy 배열 생성
ndarr1 = np.array([10, 15, 2, 8, 20, 90, 85, 44, 23, 32])
# ndarr1은 10개의 정수 요소를 가진 NumPy 배열입니다.
# 배열의 요소들은 다음과 같습니다:
# 인덱스  0   1  2  3   4   5   6   7   8   9
# 값    [10, 15, 2, 8, 20, 90, 85, 44, 23, 32]

# 인덱스 리스트 생성
idx = [2, 5, 9]
# idx는 요소를 선택할 때 사용할 인덱스 리스트입니다.
# 여기서 선택할 인덱스는 2, 5, 9입니다.

# ndarr1에서 idx에 해당하는 인덱스의 요소를 출력
print(ndarr1[idx])
# 출력: [ 2 90 32]

 
예시 8)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 생성
ndarr2d = np.array([[1, 2, 3, 4],
                    [5, 6, 7, 8],
                    [9, 10, 11, 12]])
# ndarr2d는 3개의 행(row)과 4개의 열(column)을 가지는 2차원 배열입니다.

ndarr2d[[0, 1], :]
Fancy Indexing을 사용하여 0번 행과 1번 행을 선택합니다.
**인덱스 리스트 [0, 1]**은 선택할 행의 인덱스를 나타냅니다.
**콜론 :**은 모든 열(column)을 의미합니다.
선택된 행은 다음과 같습니다:
[[ 1  2  3  4]   # ndarr2d[0, :]
 [ 5  6  7  8]   # ndarr2d[1, :]
 [ 9 10 11 12]]  # ndarr2d[2, :]
# ndarr2d[0, :] → [1, 2, 3, 4] (첫 번째 행)
# ndarr2d[1, :] → [5, 6, 7, 8] (두 번째 행)
-->
[[1 2 3 4]
 [5 6 7 8]]

 
예시 9)

import numpy as np  # NumPy 라이브러리를 가져옴

# 이모지(문자열)를 요소로 가지는 NumPy 배열 생성
ndarr1 = np.array(['🍓', '🍉', '🍌', '🍒', '🍑'])
# ndarr1은 ['🍓', '🍉', '🍌', '🍒', '🍑']라는 5개의 이모지 문자열을 포함하는 NumPy 배열입니다.

# 선택할 요소를 결정하는 불리언 리스트 생성
sel = [True, False, True, True, False]
# sel은 각 위치에서 요소를 선택할지(True) 선택하지 않을지(False)를 나타냅니다.

# 불리언 인덱싱을 사용하여 선택된 요소 출력
print(ndarr1[sel])
# 출력: array(['🍓', '🍌', '🍒'], dtype='<U1')

 
예시 10)

import numpy as np

# 2차원 NumPy 배열 생성
ndarr2d = np.array([[1, 2, 3, 4],
                    [5, 6, 7, 8],
                    [9, 10, 11, 12]])

# 조건 연산: 7보다 큰지 확인
print(ndarr2d > 7)
# 출력:
# [[False False False False]
#  [False False False  True]
#  [ True  True  True  True]]

# 불리언 인덱싱: 7보다 큰 요소만 선택
print(ndarr2d[ndarr2d > 7])
# 출력:
# [ 8  9 10 11 12]

 
3. 행렬 연산
* 넘파이에서는 다차원 배열인 ndarray를 사용하여 행렬 연산을 수행할 수 있습니다.
* 행렬 연산은 선형 대수와 관련이 깊어, 데이터 과학, 머신러닝, 통계 등 다양한 분야에서 사용됩니다.
 
3-1. 선형 대수
> 선형 대수는 벡터와 행렬을 사용해 공간과 변환을 다루는 수학의 한 분야입니다. 
* 쉽게 말해, 여러 숫자를 체계적으로 배열한 벡터(리스트 같은 것)와 행렬(숫자가 격자로 배열된 표)을 이용해 데이터를 표현하고 조작하는 방법입니다. 
* 선형 대수는 컴퓨터 그래픽스, 머신러닝, 물리학, 공학 등 다양한 분야에서 사용됩니다. 
* 예를 들어, 사진에서 색상을 조정하거나, 로봇이 움직일 경로를 계산하거나, AI가 데이터를 분석하는 데도 선형 대수가 필요합니다.
 
예시 1)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'a' 생성
a = np.array([[1, 2, 3],
              [2, 3, 4]])
# 'a'는 2개의 행(row)과 3개의 열(column)을 가지는 2차원 배열입니다.

# 2차원 NumPy 배열 'b' 생성
b = np.array([[3, 4, 5],
              [1, 2, 3]])
# 'b'도 2개의 행(row)과 3개의 열(column)을 가지는 2차원 배열입니다.

# 각 배열의 shape(형상) 출력
#2: 2개의 행
#3: 3개의 열
print(a.shape, b.shape)
-->
(2, 3) (2, 3)

 
예시 2)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'a' 생성
a = np.array([[1, 2, 3],
              [2, 3, 4]])

# 2차원 NumPy 배열 'b' 생성
b = np.array([[3, 4, 5],
              [1, 2, 3]])

# 행렬 덧셈
print(a + b)
-->
a + b = [[1+3, 2+4, 3+5],    # 첫 번째 행: 1+3=4, 2+4=6, 3+5=8
         [2+1, 3+2, 4+3]]    # 두 번째 행: 2+1=3, 3+2=5, 4+3=7
결과: [[4, 6, 8],
       [3, 5, 7]]

#행렬 뺄셈
print(a - b)
-->
a - b = [[1-3, 2-4, 3-5],    # 첫 번째 행: 1-3=-2, 2-4=-2, 3-5=-2
         [2-1, 3-2, 4-3]]    # 두 번째 행: 2-1=1, 3-2=1, 4-3=1

결과: [[-2, -2, -2],
       [ 1,  1,  1]]

#행렬 원소별 곱셈
print(a * b)
-->
a * b = [[1*3, 2*4, 3*5],    # 첫 번째 행: 1*3=3, 2*4=8, 3*5=15
         [2*1, 3*2, 4*3]]    # 두 번째 행: 2*1=2, 3*2=6, 4*3=12

결과: [[ 3,  8, 15],
       [ 2,  6, 12]]

#행렬 나눗셈
print(a / b)
-->
a / b = [[1/3, 2/4, 3/5],    # 첫 번째 행: 1/3=0.3333, 2/4=0.5, 3/5=0.6
         [2/1, 3/2, 4/3]]    # 두 번째 행: 2/1=2.0, 3/2=1.5, 4/3=1.3333

결과: [[0.33333333, 0.5       , 0.6       ],
       [2.         , 1.5       , 1.33333333]]

 
행렬 곱의 규칙
1. 첫 번째 행렬의 열(가로 숫자 개수)과 두 번째 행렬의 행(세로 숫자 개수)이 같아야 합니다.
    - 예: A가 2 ×3 행렬이고 B가 3 ×2 행렬이라면, A와 B를 곱할 수 있습니다.
2. 결과 행렬은 첫 번째 행렬의 행 개수 × 두 번째 행렬의 열 개수입니다.
    - 예: A(2 ×3) × B(3 ×2) → 결과는 2 ×2 행렬.
3. 행렬곱은 첫 번째 행렬의 한 행과 두 번째 행렬의 한 열을 각각 곱한 뒤 더해서 계산합니다.

> 행렬곱은 두 행렬을 곱해서 새로운 행렬을 만드는 연산으로, 데이터의 변환이나 계산에서 많이 사용됩니다. 
* 행렬은 숫자를 격자로 배열한 것으로, 벡터나 데이터를 다루는 데 유용합니다.

 
예시 1)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'ndarr3' 생성
ndarr3 = np.array([[1, 2, 3],
                   [1, 2, 3],
                   [2, 3, 4]])
# 'ndarr3'는 3개의 행(row)과 3개의 열(column)을 가지는 2차원 배열입니다.

# 2차원 NumPy 배열 'ndarr4' 생성
ndarr4 = np.array([[1, 2],
                   [3, 4],
                   [5, 6]])
# 'ndarr4'는 3개의 행(row)과 2개의 열(column)을 가지는 2차원 배열입니다.

# ndarr3의 shape(형상) 출력
print(ndarr3.shape)

# ndarr4의 shape(형상) 출력
print(ndarr4.shape)

-->
print(ndarr3.shape)  # 출력: (3, 3)
print(ndarr4.shape)  # 출력: (3, 2)

 
 
예시 2)

# 첫 번째 계산: 두 개의 수식 계산 및 출력
print((1*1 + 2*3 + 3*5), (1*2 + 2*4 + 3*6))

# 두 번째 계산: 첫 번째와 동일한 수식 계산 및 출력
print((1*1 + 2*3 + 3*5), (1*2 + 2*4 + 3*6))

# 세 번째 계산: 다른 수식 계산 및 출력
print((2*1 + 3*3 + 4*5), (2*2 + 3*4 + 4*6))

-->
22 28
22 28
31 40

 
 
위의 예시 2번을 간단히 쓰려면

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'ndarr3' 생성 (3x3 행렬)
ndarr3 = np.array([[1, 2, 3],
                   [1, 2, 3],
                   [2, 3, 4]])

# 2차원 NumPy 배열 'ndarr4' 생성 (3x2 행렬)
ndarr4 = np.array([[1, 2],
                   [3, 4],
                   [5, 6]])

# 행렬 곱셈 수행 (두 가지 방법)
print(ndarr3 @ ndarr4)        # @ 연산자를 사용한 행렬 곱셈
print(np.dot(ndarr3, ndarr4)) # np.dot() 함수를 사용한 행렬 곱셈
-->
[[22 28]
 [22 28]
 [31 40]]
[[22 28]
 [22 28]
 [31 40]]

 
4. 순차적인 값 생성
* NumPy에서 np.arrange() 함수는 일정한 간격으로 숫자들을 생성하는 데 사용됩니다. 
* 이 함수는 Python의 기본 range() 함수와 유사하지만, NumPy 배열을 반환하므로 수학적인 연산이 가능합니다.
 
예시 1)

# 1부터 10까지의 정수를 생성하는 range 객체를 arr1에 할당
arr1 = range(1, 11)

# arr1 출력
print(arr1) # 출력: range(1, 11)


print(list(range(5)))       # [0, 1, 2, 3, 4]
print(list(range(1, 6)))    # [1, 2, 3, 4, 5]
print(list(range(1, 10, 2)))  # [1, 3, 5, 7, 9] (2씩 증가)

 
예시 2)

# 1부터 10까지의 정수를 생성하는 range 객체 생성
arr1 = range(1, 11)

# for 반복문을 사용하여 arr1의 각 요소를 출력
for i in arr1:
    print(i, end=' ')
-->
1 2 3 4 5 6 7 8 9 10

 
예시 3)

import numpy as np  # NumPy 라이브러리를 가져옴

# 1부터 10까지의 정수를 생성하는 NumPy 배열 'arr2' 생성
arr2 = np.arange(1, 11)

# arr2 출력
print(arr2) # 출력 : [ 1  2  3  4  5  6  7  8  9 10]

# arr2의 타입 출력
print(type(arr2)) # 출력 : <class 'numpy.ndarray'>


#예제2)
# 0부터 4까지 생성
arr1 = np.arange(5)  
print(arr1)  # 출력: [0 1 2 3 4]

# 1부터 10까지 생성 (2씩 증가)
arr2 = np.arange(1, 11, 2)  
print(arr2)  # 출력: [1 3 5 7 9]

# 실수를 사용하여 0부터 2까지 0.5씩 증가
arr3 = np.arange(0, 2, 0.5)  
print(arr3)  # 출력: [0.  0.5 1.  1.5]

 
5. 정렬
* NumPy의 np.sort() 함수는 배열을 정렬하는 데 사용됩니다. 
* 이 함수는 기본적으로 원래 배열을 변경하지 않고 정렬된 배열의 복사본을 반환합니다.
 
예시 1)

ndarr1 = np.array([1, 10, 5, 7, 2, 4, 3, 6, 8, 9])
print(ndarr1)
-->
[ 1 10  5  7  2  4  3  6  8  9]

 
예시 2)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열 'ndarr1' 생성
ndarr1 = np.array([1, 10, 5, 7, 2, 4, 3, 6, 8, 9])

# ndarr1을 오름차순으로 정렬한 결과를 출력 (정렬된 복사본 반환) #오름차순 정렬
print(np.sort(ndarr1)) # 출력 : [ 1  2  3  4  5  6  7  8  9 10]

# 원본 배열 'ndarr1'을 다시 출력 (원본은 변경되지 않음) 
print(ndarr1)  # 출력 : [ 1 10  5  7  2  4  3  6  8  9]

 
예시 3)

import numpy as np  # NumPy 라이브러리를 가져옴

# NumPy 배열 'ndarr1' 생성
ndarr1 = np.array([1, 10, 5, 7, 2, 4, 3, 6, 8, 9])

# 오름차순으로 정렬한 뒤, 마지막 원소를 제외한 배열을 출력  #내림차순 정렬
print(np.sort(ndarr1)[:-1]) # 출력 : [1 2 3 4 5 6 7 8 9]

#만약 내림차순으로 정렬하고 싶다면, 다음과 같이 [::-1] 슬라이싱을 사용합니다
print(np.sort(ndarr1)[::-1])  # 출력 : [10  9  8  7  6  5  4  3  2  1]

 
예시 4)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'ndarr2d' 생성
ndarr2d = np.array([[11, 10, 12, 9],
                    [3, 1, 4, 2],
                    [5, 6, 7, 8]])

# ndarr2d 배열의 shape(형상) 출력
print(ndarr2d.shape) # 출력 : (3, 4)


11  10  12  9    ← 첫 번째 행 (row 0)
 3   1   4  2    ← 두 번째 행 (row 1)
 5   6   7  8    ← 세 번째 행 (row 2)

^   ^   ^   ^
|   |   |   |
열 0 열 1 열 2 열 3

 
예시 5)
axios의 정렬 방법
axis=0: 열(column) 단위로 정렬
axis=1: 행(row) 단위로 정렬
axis=-1: 배열의 마지막 축을 기준으로 정렬

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'ndarr2d' 생성
ndarr2d = np.array([[11, 10, 12, 9],
                    [3, 1, 4, 2],
                    [5, 6, 7, 8]])

# 열 단위로 오름차순 정렬 (axis=0은 열 기준 정렬을 의미함)
**axis=0**는 열(column) 단위로 정렬한다는 의미입니다.
각 열을 개별적으로 오름차순 정렬합니다.

np.sort(ndarr2d, axis=0)
sorted_ndarr2d = np.sort(ndarr2d, axis=0)
첫 번째 열: [11, 3, 5] → [3, 5, 11]
두 번째 열: [10, 1, 6] → [1, 6, 10]
세 번째 열: [12, 4, 7] → [4, 7, 12]
네 번째 열: [9, 2, 8] → [2, 8, 9]

# 정렬된 배열 출력
print(sorted_ndarr2d) 
-->
array([[ 3,  1,  4,  2],
       [ 5,  6,  7,  8],
       [11, 10, 12,  9]])

 
예시 6)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'ndarr2d' 생성
ndarr2d = np.array([[11, 10, 12, 9],
                    [3, 1, 4, 2],
                    [5, 6, 7, 8]])

# 행 단위로 오름차순 정렬 (axis=1은 행 기준 정렬을 의미함)
sorted_ndarr2d = np.sort(ndarr2d, axis=1)

첫 번째 행: [11, 10, 12, 9] → [9, 10, 11, 12]
두 번째 행: [3, 1, 4, 2] → [1, 2, 3, 4]
세 번째 행: [5, 6, 7, 8] → [5, 6, 7, 8] (이미 정렬된 상태)

# 정렬된 배열 출력
print(sorted_ndarr2d)
-->
array([[ 9, 10, 11, 12],
       [ 1,  2,  3,  4],
       [ 5,  6,  7,  8]])

 
예시 7)

import numpy as np  # NumPy 라이브러리를 가져옴

# 2차원 NumPy 배열 'ndarr2d' 생성
ndarr2d = np.array([[11, 10, 12, 9],
                    [3, 1, 4, 2],
                    [5, 6, 7, 8]])

# 행 단위로 오름차순 정렬 후, 각 행을 뒤집어서 내림차순으로 정렬
#[:, ::-1]**는 모든 행(:)에 대해 각 행을 뒤집어서 내림차순으로 만듭니다.
::-1은 배열을 역순으로 뒤집습니다
sorted_ndarr2d = np.sort(ndarr2d, axis=1)[:, ::-1] 

#즉, axis=0: 열(column) 기준으로 정렬
#axis=1: 행(row) 기준으로 정렬


# 정렬된 배열 출력
print(sorted_ndarr2d)

-->
array([[12, 11, 10,  9],
       [ 4,  3,  2,  1],
       [ 8,  7,  6,  5]])

 
예시 8)

ndarr2d = np.array([[11, 10, 12, 9],
                    [3, 1, 4, 2],
                    [5, 6, 7, 8]])
 np.sort(ndarr2d, axis=-1) # -1은 배열의 마지막 축을 기준으로 정렬
 -->
 axis=-1: 배열의 마지막 축을 기준으로 정렬합니다.
2차원 배열의 경우, **마지막 축은 각 행(row)**을 의미합니다.
따라서, 각 행을 개별적으로 오름차순으로 정렬합니다.
첫 번째 행: [11, 10, 12, 9] → [9, 10, 11, 12]
두 번째 행: [3, 1, 4, 2] → [1, 2, 3, 4]
세 번째 행: [5, 6, 7, 8] → [5, 6, 7, 8] (이미 정렬된 상태)
-->
array([[ 9, 10, 11, 12],
       [ 1,  2,  3,  4],
       [ 5,  6,  7,  8]])
       
즉,       
axis=0: 열(column) 단위로 정렬
axis=1: 행(row) 단위로 정렬
axis=-1: 배열의 마지막 축을 기준으로 정렬

 
예시 9)

import numpy as np

ndarr2d = np.array([[11, 10, 12, 9],
                    [3, 1, 4, 2],
                    [5, 6, 7, 8]])

# 행 단위로 내림차순 정렬
sorted_ndarr2d = np.sort(ndarr2d, axis=1)[:, ::-1]

print("원본 배열:")
print(ndarr2d)

print("\n행 단위로 내림차순 정렬된 배열:")
print(sorted_ndarr2d)
-->
원본 배열:
[[11 10 12  9]
 [ 3  1  4  2]
 [ 5  6  7  8]]

행 단위로 내림차순 정렬된 배열:
[[12 11 10  9]
 [ 4  3  2  1]
 [ 8  7  6  5]]
728x90
LIST

'LLM(Large Language Model)의 기초 > 데이터 분석' 카테고리의 다른 글

5. 상권_데이터셋  (6) 2024.12.19
3. Matplotlib  (4) 2024.12.19
4. Online Retail 데이터셋  (1) 2024.12.18
2-2) 판다스(Pandas)  (4) 2024.12.18
2. 판다스(Pandas)  (4) 2024.12.17