데이터 분석 학습일지🐣

18일차 - 파이썬 시각화 실습(Numpy, Pandas, Matplotlib, Seaborn)

boiled egg 2023. 7. 14. 12:29

Date : 2023-07-13

Topic : 파이썬 시각화 실습(Numpy, Pandas, Matplotlib, Seaborn)


Note

Numpy

: 다차원 배열을 쉽고 효율적으로 계산, 데이터 분석을 할 때 Pandas 와 거의 항상 함께 연계해 사용

  1. 데이터란 이미지, 오디오, 텍스트, 숫자 등 다양한 형태와 크기로 존재
  2. 모든 데이터는 결국, 숫자의 배열 형태로 해석
  3. Numpy 는 Python 에서 모든 데이터 자료형을 분석하고 계산하기 위한 라이브러리
  • library install : 라이브러리가 없다면 설치
# !pip install [library name]
!pip install numpy
!pip install pandas
!pip install matplotlip.pyplot
!pip install seaborn
  • import library : 설치된 라이브러리를 불러오기
# import [library name] (as alias 생략 가능)
import numpy as np
import pandas as pd
import matplotlib as plt
import seaborn as sns
# 리스트와 비슷해보이지만 type 명령으로 자료형을 보면 ndarray임.
ar=np.array([0,1,2,3,4,5,6,7,8,9])
print(ar)	# [0 1 2 3 4 5 6 7 8 9]
print(type(ar))	# <class 'numpy.ndarray'>​
  • list와 ndarray 차이점
    • ndarray : N-Dimensional Array의 약자. 말 그대로 N차원의 다차원 배열 자료 구조
# List
data=[0,1,2,3,4,5,6,7,8,9]
data=list(range(10))
data		# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 2의 배수를 리스트로 만드려면 반복문을 사용해야 한다.
answer=[]

for di in data:
    answer.append(2*di)
answer		# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# 그냥 data에 2배를 하면
print(data*2)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 물리적으로 2배가 나온다.
# ndarray
x=np.array(data)
x		# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# ndarray는 벡터화 연산으로 list와 차이점이 있다.
x*2		# array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])
a=np.array([1,2,3])
b=np.array([10,20,30])

# 벡터 연산
a*2+b		# array([12, 24, 36])
  • 논리 연산
(a==2)&(b>10)   # and 논리연산
# array([False,  True, False])

(a==2)|(b>10)   # or 논리연산
# array([False,  True,  True])

Array(배열)

: 같은 타입을 가지는 데이터가 나열된 집합

  1. 축(axis)의 수에 따라 N차원으로 나타낼 수 있다.
  2. 다중 리스트 구조와 다른 점은, 배열은 같은 데이터 타입 으로 이루어져 있다

  • N차원 array
# 1D array
array1 = np.array([1,2,3])
np.shape(array1)
  • 2차원 배열 = matrix (행렬), 리스트의 리스트(list of list)를 이용하면 생성할 수 있다.
    • 가로줄: 행(row)
    • 세로줄: 열(column)
# 2D array
array2 = np.array([[1,2,3],
                   [4,5,6]])
np.shape(array2)
  • 2차원 배열의 행과 열의 개수 구하기
c=np.array([[0,1,2],[3,4,5]])
print(c)

# [[0 1 2]
# [3 4 5]]

# 행의 개수
len(c)  	# 2

# 열의 개수
print(c[0])	# [0 1 2]
len(c[0])	# 3
# 3D array
array3 = np.array([[[1,2,3],
                    [4,5,6]],
                    [[7,8,9],
                    [10,11,12]]])
np.shape(array3)
d=np.array([[[1,2,3,4],
             [5,6,7,8],
             [9,10,11,12]],
            [13,14,15,16],
            [17,18,19,20],
            [21,22,23,24]])
            
# <ipython-input-72-86e10f7e6312>:1: 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.
  • Numpy 배열 생성하는 방법
    • 리스트 자료형에서 numpy 로 변환
    • numpy 자체 생성 함수 활용
    • 파일(이미지 등) 기반 배열 생성
  • 리스트 자료형에서 numpy 변환
mylist = [1,2,3]
np.array(mylist)	# array([1, 2, 3])
mylist = [[1,2,3], [4,5,6]]
np.array(mylist)

'''op:
array([[1, 2, 3],
       [4, 5, 6]])
'''
  • 데이터 타입(type) 지정
# 정수
np.array([1,2,3], dtype=int)	# array([1, 2, 3])

# 실수
np.array([1,2,3], dtype=float)	# array([1., 2., 3.])

# 유니코드 문자열
np.array(['1','2','3'])		# array(['1', '2', '3'], dtype='<U1')

# 문자열에서 정수형으로
np.array(['1','2','3'], dtype=int)	# array([1, 2, 3])
  • 자체 생성 함수등간격 배열 생성
# np.arrange
np.arange(10)		# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

np.arange(2,10)		# array([2, 3, 4, 5, 6, 7, 8, 9])

np.arange(2, 10, 2)	# array([2, 4, 6, 8])

# np.linspace -> 그래프 그릴 때 유용
np.linspace(1, 10, 5)	# array([ 1.  ,  3.25,  5.5 ,  7.75, 10.  ])

np.linspace(1, 10, 4)	# array([ 1.,  4.,  7., 10.])

슬라이싱 (Slicing)

  • 축(axis) 을 따라 자르듯이 배열을 조작하는 방법 (원하는 부분만 추출하거나, 형태 변환)
  • 슬라이싱 기준

arr [ 행(row) 인덱스, 열(column) 인덱스, ... N축 인덱스]

arr = np.array([[1, 2, 3, 4], 
                [5, 6, 7, 8], 
                [9, 10, 11, 12], 
                [13, 14, 15, 16]])

위 배열을 슬라이싱↓

# 행 기준으로 슬라이싱
arr[0]		# array([1, 2, 3, 4])

arr[0,:]	# array([1, 2, 3, 4])

# 열 기준으로 슬라이싱
arr[:,0]	# array([ 1,  5,  9, 13])

# 간격을 지정해서 슬라이싱
arr[::2]

'''
array([[ 1,  2,  3,  4],
       [ 9, 10, 11, 12]])
'''

# 2, 3행 슬라이싱
arr[1:3]

'''
array([[ 2,  3],
       [ 6,  7],
       [10, 11],
       [14, 15]])
'''

# 4 열 슬라이싱
arr[:, -1]		# array([ 4,  8, 12, 16])

# 1,2행, 2,3열 슬라이싱
arr[0:2, 1:3]

'''
array([[2, 3],
       [6, 7]])
'''

 

r=range(1,21)
x=np.array(r)
x

# 3의 배수
x[x%3==0]		# array([ 3,  6,  9, 12, 15, 18])

# 4로 나누면 나머지 1
x[x%4==1]		# array([ 1,  5,  9, 13, 17])

# 3으로 나누어지고, 4로 나누면 1이 남는 수 (합집합)
x[(x%3==0)&(x%4==1)]	# array([9])

Pandas

: 시리즈(Series) 클래스데이터 프레임(Data Frame) 클래스를 제공한다.

  • Series = Value + Index
  • Series의 인덱스는 index 속성으로 접근할 수 있다.
  • (추가 예정)
import pandas as pd
s=pd.Series([9904312, 3448737, 2890451, 2466052],
            index=["서울", "부산", "인천", "대구"])
s

'''op:
서울    9904312
부산    3448737
인천    2890451
대구    2466052
dtype: int64
'''
s.name='인구'
s.index.name='도시'
s

'''op:
도시
서울    9904312
부산    3448737
인천    2890451
대구    2466052
Name: 인구, dtype: int64
'''
# 넘파이처럼 벡터화 연산 가능(시리즈 값만 적용되고 인덱스값은 변경X)
s/1000000

'''op:
도시
서울    9.904312
부산    3.448737
인천    2.890451
대구    2.466052
Name: 인구, dtype: float64
'''
  • 시리즈 인덱싱
s
'''
도시
서울    9904312
부산    3448737
인천    2890451
대구    2466052
Name: 인구, dtype: int64
'''

s[1]		# 3448737

s['부산']	# 3448737

s[3], s['대구']	# (2466052, 2466052)

 

  • 딕셔너리 원소는 순서를 가지지 않으므로 시리즈의 데이터도 순서가 보장되지 않는다. 만약 순서를 정하고 싶다면 인덳를 리스트로 지정해야 한다.
s2=pd.Series({'서울':9631492, '부산':3393191, '인천':2632035, '대전':1490158},
             index=['부산', '서울', '인천', '대전'])	# 인덱스로 순서 지정
s2

'''op: 
부산    3393191
서울    9631492
인천    2632035
대전    1490158
dtype: int64
'''
# index 기반 연산
ds=s-s2 	# key값이 같은 것끼리 연산
ds

'''op:
대구         NaN	# 대구와 대전의 경우 각각 2010년 자료, 2015년 자료가 모두 존재X
대전         NaN	# Not a Number라는 값을 가지게 된다.
부산     55546.0
서울    272820.0
인천    258416.0
dtype: float64
'''
ds.notnull()	# Null이 아닌 위치에 True

'''op:
대구    False
대전    False 
부산     True
서울     True
인천     True
dtype: bool
'''

데이터 갱신, 추가, 삭제

: 인덱싱을 이용하여 딕셔너리처럼 데이터를 update or add


데이터프레임 클래스

  • 데이터프레임에서 열 라벨로 시리즈를 인덱싱하면 시리즈가 된다. 이 시리즈를 다시 행 라벨로 인덱싱하면 개별 데이터가 나온다.
data = {
    "2015": [9904312, 3448737, 2890451, 2466052],
    "2010": [9631482, 3393191, 2632035, 2431774],
    "2005": [9762546, 3512547, 2517680, 2456016],
    "2000": [9853972, 3655437, 2466338, 2473990],
    "지역": ["수도권", "경상권", "수도권", "경상권"],
    "2010-2015 증가율": [0.0283, 0.0163, 0.0982, 0.0141]
}   # 딕셔너리
columns = ["지역", "2015", "2010", "2005", "2000", "2010-2015 증가율"] # LIST
index = ["서울", "부산", "인천", "대구"] # LIST

# data:딕셔너리, index/columns: 리스트
df=pd.DataFrame(data, index=index, columns=columns)
print(df)
df

output