데이터 분석 학습일지🐣
18일차 - 파이썬 시각화 실습(Numpy, Pandas, Matplotlib, Seaborn)
boiled egg
2023. 7. 14. 12:29
Date : 2023-07-13
Topic : 파이썬 시각화 실습(Numpy, Pandas, Matplotlib, Seaborn)
Note
Numpy
: 다차원 배열을 쉽고 효율적으로 계산, 데이터 분석을 할 때 Pandas 와 거의 항상 함께 연계해 사용
- 데이터란 이미지, 오디오, 텍스트, 숫자 등 다양한 형태와 크기로 존재
- 모든 데이터는 결국, 숫자의 배열 형태로 해석
- 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(배열)
: 같은 타입을 가지는 데이터가 나열된 집합
- 축(axis)의 수에 따라 N차원으로 나타낼 수 있다.
- 다중 리스트 구조와 다른 점은, 배열은 같은 데이터 타입 으로 이루어져 있다
- 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