본문 바로가기
데이터분석/Numpy

[Python] Numpy 기초 _벡터 연산과 데이터 핸들링

by nemonemonemo 2025. 8. 18.
  • 주어진 데이터 수집/ 가공/변형/결과 : 파이썬
    • 기본적인 파이썬 문법
    • 파이썬 계열의 데이터 처리 패키지
      • pandas →DF
      • 하지만 근본은 numpy: array

numpy

: 데이터를 처리하는 과정에서 가장 기본이 되는 패키지

numerical python

  • 수치 연산
  • 쌩파이썬의 자료형으로 연산/ 벡터 산수가 불편함 ⇒ 모든 원소에 일괄 적용 “벡터 연산” 자료형 ⇒ 수식상 표현을 그대로 코드화 가능

pandas/ scikit-learn / TF/ PyTorch 에서 가장 기본이 되는 자료형

anaconda로 설치하면 → numpy, pandas 기본 설치 되어 있는 패키지 → 불러다가 사용만 하면 됨

colab에서는 이미 설치가 되어있음 단, colab은 자기가 버전 수정을 해야함 (업그레이드는 원하지 않아도 함) 이래서 중간에 코드가 되다가 밥 먹고 오면 안 되는 경우도 있음 이제는 많이 안정회 되긴 함

import numpy as np
import pandas as pd

# 지금 내가 사용하는 패키지의 버전!!!!
pd.__version__ # 언더바 2개 앞뒤로 
#2.2.2

np.__version__
#2.0.2
# --> 오늘 기준으로 2.3.0인데,,약간 올드 버전 사용함!!!
#     이유 : 다른 패키지에 연동이 되고,,1과 2가 많이 달라서 호환성이 문제가
#            pytorch 하고,,,,

numpy를 만들게 된 이유

  • 수치 연산을 파이썬에서 하자
  • 기존의 파이썬 자료형
    • 리스트, 튜플, dict etc… ⇒ 수치 연산에 특화되지 않음
  • 수치 연산 적당한 자료형 제안→ numpy 만들게 됨
    • 벡터 연산
    • 개별 원소 중심이 아니라, 기능/액션 중심의 표현
    • 기능 중심의 코드화
  • 태생이 파이썬 → 상당히 느린 경향이 있지만 대신 편하게 코드화됨
  • 실제 개발/시스템 → 다른 언어로 같이 사용하는 경우 있음

쌩 파이썬

  • 리스트 → 값을 모아두자 → 벡터와 유사함
  • 2차원 좌표 평면 : 차원은 없지만 오/열 맞춰서 차원을 유사 표현
  • ⇒ 모든 값에 일괄 적용 : 벡터 연산의 기능이 없음 모든 값을 롤링 : for → LC
  • ex) x = [1,2,3] 모든 원소에 +100을 하자
    • ⇒ [1+100, 2+100, 3+100]
    • 규칙 : 벡터로 표현 x + 100
    a = [ 100,200,300,400,500]
    a
    #[100, 200, 300, 400, 500]
    
    # 쌩 파이썬의 리스트+ 5개 원소 ==> 모든 원소에 +10을 하자!!!!!
    # m1) 그냥 돌리기 : 값 자체 vs 정수인덱스
    b = []
    for i in a:
        b.append( i + 10)
    b
    #[110, 210, 310, 410, 510]
    
    # m2) LC
    [i+10 for i in a]
    #[110, 210, 310, 410, 510]
    
    a + 10 # ==> 이렇게 수식적인 벡터 표현을 그대로 코드화 되면 좋을 텐데...
    #오류남
    
    # m3) numnpy의 array 자료형 --> 내부에 벡터연산이 되도록 만든 새로운 자료형!!!
    #  ==> 외부 개발잘/커뮤니티 중심으로 만들어서 배포/유지 보수..
    a_arr = np.array( a )
    a_arr
    #array([100, 200, 300, 400, 500])
    
    b = []
    for i in a_arr:
        b.append(i+10)
    b
    #[np.int64(110), np.int64(210), np.int64(310), np.int64(410), np.int64(510)]
    
    a_arr + 10
    #array([110, 210, 310, 410, 510])
    

  • 벡터연산이 기본적으로 "기능 중심의 표현"
  • 코드 작성 "기능 중삼"으로 코드 작성이 용이하게 되고
  • +파이썬과 손발이 잘 맞게 되었고
  • +비전공 영역에서 파이썬 기반의 데이터 핸들링이 확 퍼지게 되었다.
  • --> numpy ---> pandas
# ex)
x = [ 1,2,3,4,5]
y = [10,20,30,40,50]
# --> ( 1+10, 2+20, 3+30, 4+40, 5+50)
#     수학적인 벡터라 생각하면 :  x+ y

# m1) 쌩파이썬
z = []
for i in range(len(a)):
    # 임의의 i번째 원소를 가지고,,,뭘 할지
    z.append( x[i] + y[i])
z
#[11, 22, 33, 44, 55]

# m2) 쌩파이썬 ---> LC
[ x[i] + y[i]  for i in range(len(a)) ]
#[11, 22, 33, 44, 55]

# m3) numpy의 array 자료형으로 변경!!!
x_arr = np.array( x)
y_arr = np.array(y)

x_arr
#array([1, 2, 3, 4, 5])

y_arr
#array([10, 20, 30, 40, 50])

x_arr + y_arr
#array([11, 22, 33, 44, 55])

그래서 이 내용이 나랑 무슨 상관인가?

  • 앞으로 데이터 핸들링 하는 과정에서도 고려할 요소가 개별 원소값이 기준이 아니라 줄 단위(row, col)으로 무엇을 할지 **“기능 중심”**으로 생각하고, → 그걸 그대로 코드화 함

차원에 대한 내용을 추가적으로 다루고 있음

  • 쌩 파이썬의 리스트
    • 값들을 모아두자
    • 값 → 숫자, 문자, 리스트 … ect
    • 차원에 대한 정보는 없음
    • 일괄적용도 없음
    m=[
       [1,2,3],
       [5,6,7]
       ]
    m[가로줄][세로줄]
    
  • numpy의 array
    • 값들을 모아두는 것
    • 값 → 숫자, 문자, 리스트 etc…
    • 차원에 대한 정보를 생성 (오/열/값 종류) → 차원으로 인식함
    • 기능(벡터 연산은 기본)
    a = [ 1,2,3,"a", ["a","b","c",[1,2,3]]]
    a
    #[1, 2, 3, 'a', ['a', 'b', 'c', [1, 2, 3]]]
    
    np.array(a)
    #오류남
    
    np.array( [1,2,3,["a","b"]])
    #오류남
    #이렇게까지 복잡한 건 안 해줌 
    
    np.array( [1,2,3,"a","b"])
    #array(['1', '2', '3', 'a', 'b'], dtype='<U21')
    # --> 현실적으로 이렇게 쓸 일이 없어요!!!!
    #적당한 수준으로는 해준다
    
    test_arr = np.array( [ 1,2,3,4,5])
    test_arr
    #array([1, 2, 3, 4, 5])
    
    test_arr.dtype
    #dtype('int64')
    
    test_arr + 1
    #array([2, 3, 4, 5, 6])
    
    test_arr * 10
    #array([10, 20, 30, 40, 50])
    
    test_arr.ndim
    #1
    
    test_arr.shape
    #(5,)
    
    # cf) 2차원 평면/ 행렬
    test = [
        [1,2,3],
        [4,5,6]
    ]
    test
    #[[1, 2, 3], [4, 5, 6]]
    
    test_arr = np.array( test)
    test_arr
    #array([[1, 2, 3],
    #       [4, 5, 6]])
    
    test_arr.ndim
    #2
    
    test_arr.shape
    #(2, 3)
    
    len(test_arr)
    #2
    # --> 2차원의 자료형이지만,,,
    #     파이썬의 입장에서 큰 틀 기준 : 2개 원소,,,,,
    #     2차원 행렬에서는 가로줄 수
    # --> len(df) : 2차원 가로줄 수 == 데이터 수
    
    test_arr.shape[0]
    #2
    
    # 참고) test 라는 리스트 기반의 1번 가로줄, 2번 세로줄 값 : 2
    #      ==> 접근 방식...
    test[0][1]
    #2
    
    test_arr[0][1]
    #np.int64(2)
    
    test_arr[ 0, 1] # -->차원에 대한 양식 --> 가로/세로 인덱스기반으로 바로 접근!!
    #np.int64(2)
    
    test[0,1] # 쌩파이썬은 불가능!!! --> 순차적으로 하나씩 접근만 가능!!!
    #오류남
    
    # 리스트 --> 값에 대한 접근 : 정수인덱스!!!
    #        --> 여러개 & 규칙 : 슬라이싱!!!
    a = [10,20,30,40,50]
    a_arr = np.array(a)
    
    a[:3]
    #[10, 20, 30]
    
    a_arr[:3]
    #array([10, 20, 30])
    
    a[::2]
    #[10, 30, 50]
    
    a_arr[::2]
    #array([10, 30, 50])
    
    # 참고) a의 원소중에서 0,1,3번째 원소만 보자...
    a[ [0,1,3]]
    #오류남
    
    a_arr[ [0,1,3]] 
    #array([10, 20, 40])
    # --> 인덱스 자리에 내가 보고자 하는 것들을 리스트업!!
    #                     알아서 그것들만 보여준다!! 필터링!!!!
    

ref : https://numpy.org/doc/stable/reference/arrays.dtypes.html

  • numpy가 수치연산이 일단 제일 큰 목적 : 여러가지 수치형 자료 유형을 만들어 둠
  • float 16, 32, 64, …etc
b = [1,2,3]
b_arr = np.array(b)
b_arr
#array([1, 2, 3])

b_arr.dtype
#dtype('int64')

b_arr = np.array(b, dtype=np.float32)
b_arr # --> dtype : 넘파이가 만들어둔 자료형으로 변환을 요청!
#array([1., 2., 3.], dtype=float32)

b_arr.astype(np.int32)
#array([1, 2, 3], dtype=int32)

str(1) #'1'
int("1") #1

# ==> 파이썬에서 했던 대로
#     자료형에 대한 변경 왔다 갔다 할 수 잇음
# --> astype() 공식적인 기능/ 메서드 통해서 상호 변환 

넘파이의 array에서 인덱스 연습

m = [
      [0,1,2,3,4,5],
      [10,11,12,13,14,15],
      [20,21,22,23,24,25],
      [30,31,32,33,34,35],
      [40,41,42,43,44,45],
      [50,51,52,53,54,55]
]
m

list(range(0,6,1)) #벡터연산 안 됨
#[0, 1, 2, 3, 4, 5]

np.arange(0,6,1) # 벡터연산 가능 
#array([0, 1, 2, 3, 4, 5])

np.arange(0,51,10)[:,np.newaxis]
#array([[ 0],
#       [10],
#       [20],
#       [30],
#       [40],
#       [50]])
# 1차원에 축을 추가해서 2차원으로 확장하는 것 
#보통 이렇게 .newaxis 활용해 직접 만들어서 할 일은 거의 없지만 알아둬

np.arange(0,51,10)[:,np.newaxis] + np.arange(0,6,1)
#array([[ 0,  1,  2,  3,  4,  5],
#       [10, 11, 12, 13, 14, 15],
#       [20, 21, 22, 23, 24, 25],
#       [30, 31, 32, 33, 34, 35],
#       [40, 41, 42, 43, 44, 45],
#       [50, 51, 52, 53, 54, 55]])

a=np.arange(0,51,10)[:,np.newaxis] + np.arange(0,6,1)
a
#array([[ 0,  1,  2,  3,  4,  5],
#       [10, 11, 12, 13, 14, 15],
#       [20, 21, 22, 23, 24, 25],
#       [30, 31, 32, 33, 34, 35],
#       [40, 41, 42, 43, 44, 45],
#       [50, 51, 52, 53, 54, 55]])

type(a)
#numpy.ndarray

a.ndim
#2

a.shape
#(6, 6)

a.dtype
#dtype('int64')

  • 목적 : 2차원에서 우너하는 값에 대한 접근을 해보자
    • 기준 생파이썬 리스트의 관점: 순차적으로 접근 -> 어느 가로줄-->어느 세로줄
  • 2차원 numpy의 array접근
      1. 쌩 파이썬 입장
      • 가로 접근 후 → 원하는 세로 접근
      • a[가로][세로]
      1. +++원하는 위치에 대한 좌표로 한 번에 접근
      • a[가로, 세로]
a[1][1]
#np.int64(11)

a[ 1,1 ]
#np.int64(11)

# Q) 주황색
a[0][3:5]
#array([3, 4])

a[ 0, 3:5]
#array([3, 4])

#Q) 세로 빨간 줄: 가로줄 --> 모든 가로줄, 세로줄 --> 2번째 줄
a[:,2]
#array([ 2, 12, 22, 32, 42, 52])

#Q) 초록색 덩어리
# ==> 가로: 규칙 존재 & 여러개 -> 2번째 가로줄 부터 끝까지 퐁당퐁당
#     세로: 규칙 존재 & 여러개 -> 0번째 세로줄 부터 끝까지 퐁당퐁당
a[2::2, ::2]
#array([[20, 22, 24],
#       [40, 42, 44]])

#Q) 우측 하단
# ==> 가로 ; 4번째 줄 부터~~~
#     세로 : 4번째 줄 부터~~~
a[4:, 4:]
#array([[44, 45],
#       [54, 55]])

불리언 인덱싱

  • 인덱스
    • 정수, 슬라이싱 (쌩 파이썬 리스트도 다 가능)
    • 가로/세로 위치(들)
    • 여기에 +++ 조건식을 넣으려고함 ⇒ 이게 불러언 인덱싱
  • 불리언 인덱싱
    • numpy의 array 자료형 인덱스 [ ] 안에 “조건식”이 들어갈 수 있음
    • 의미
      • 조건식에 대한 데이터 필터링
      • sql) where, having ~~ etc
      • pandas) 데이터 필터링을 할 때 : 인덱스 자리에 조건식
  • 왜 가능할까?
    • 벡터연산 ! ⇒ 모든 원소에 일괄 적용
test_arr = np.arange(1,11,1)
test_arr
#array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

#ex) 5보다 작은 값들만 추리고 싶다 
#    sql : ~~where a<5 etc
#    쌩파이썬 : LC + (for + if)

test_arr + 5
#array([ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15])

test_arr < 5
#array([ True,  True,  True,  True, False, False, False, False, False, False])

test_arr[test_arr < 5]
#array([1, 2, 3, 4])

# *** 인덱스 자리에 조건식이 들어가게 됨
#    모든 원소에 해당 조건식이 만족하는지 체크
#    Y/N(True/False) 논리값 불리언값
# ==> array의 인덱스 자리에 들어가면 True에 해당하는 값만 보여줌 
# *** 원하는 조건에 대한 필터링 ***

참고) numpy 수식 연산 패키지

  • 산수 연산에 특화가 되어 있습니다..여러 수식 함수들이 있음.!!!
  • 메뉴얼. gpt 이용해서 필요한 거 검색해서 가져다 사용하시면 된다.
test_arr
#array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

sum(test_arr) # --> 파이썬의 sum 함수를 활용해서 진행!!!!
#np.int64(55)

test_arr.sum() 
#np.int64(55)
# --> numpy가 미리 만들어둔 sum 함수/메서드를 사용해서 구해줘
#더 큰 데이터에서는 좀 더 효율적 

numpy 핵심

    1. 기능 : 여러개의 값을 모아둠, 오/열 맞춰서 + 형식까지 맞춰서
    1. 연산
    • 모든 원소에 일괄 적용 벡터연산을 기본 + 차원
    • 내가 직접 개별 원소 롤링 안 해도 됨 → 기능 중심 코드
    1. 값에 대한 접근
    • 순차적으로 접근 (리스트) vs 직접 접근
    • array[정수]
    • array[슬라이싱]
    • array[리스트] : 2D 이상에서는 좀 주의해야함
    • ****array[조건식] : 불리언 인덱싱 ⇒ 필터링
    • ++2D array : 가로/세로 각기 독립적으로 접근
      • array[가로, 세로]
      • array[가로정수, 세로정수]
      • array[가로슬라이싱, 세로슬라이싱]
      • array[가로정수, 세로 슬라이싱] ** 혼합도 가능
      • array[가로 조건식, 세로 조건식] : 원하는 가로/세로 필터링 가능
  • 참고 ) 속성
    • arr.ndim
    • arr.shape
    • arr.dtype