본문 바로가기
ML 인공지능

[Python] 데이터분석을 위한 라이브러리 Numpy, Pandas 전체 요약

by 딧피 2021. 11. 9.
728x90
반응형

**본 내용은 Alice 의 데이터 분석을 위한 라이브러리 과정을 수강하면서 , 직접 궁금한 것을 찾아보고 공부하며 정리한 내용임.

 

1. 데이터 핸들링을 위한 라이브러리 Numpy

Numpy 란? : Numerical Python

대규모 다차원 배열을 다룰수 있게 도와주는 python 라이브러리 'NumPy'

 

사용이유?

- 데이터의 대부분 숫자 배열로 볼수 있다. (객체로 고차원 배열 제공, 관련된 메소드 제공)

- 반복문 없이 배열 처리 가능

- 리스트에 비해 빠른 연산 지원, 메모리 효율적 사용 (연산의 벡터화)
- 수많은 수학 연산을 기본 제공

- 다른 패키지에서도 Numpy 배열을 기초 자료형으로 사용

 

 

사용 어떻게?

- 1. list 배열 생성 및 출력 형태 확인

list_arr = list(range(5))      #[0,1,2,3,4] - 콤마로 구분!
print(type(list_arr))            #<class'list'>

 

- 2. numpy 배열 생성 및 출력 형태 확인
ndarray = n차원의 배열 (n-dimensional array)

import numpy as np

np_arr = np.array(range(5))

pritn(np_arr)                         #[0 1 2 3 4] - 공백으로 구분! -  list는 콤마! 

print(type(np_arr))               #<class 'numpy.ndarray'>  - 클래스의 타입은 ndarray이다.


np.linspace(0, 10, 5)            # 0과 10 사이 5개의 요소를 가지는 array 생성,

                                               # 요소 개수는 default가 50
                                               # restep옵션으로 간격확인 가능

 

** arange 함수는 일정 범위, 패턴의 numpy 배열을 생성

** linspace 함수는 일정범위에 일정한 간격으로 요소를 가지는 numpy 배열을 생성

** zeros함수 0 으로 이루어진 numpy 배열생성

** ones함수는 

 

사용시 주의사항

- 리스트와 달리 같은 데이터 타입만 저장가능 (arr이면 arr, float64면 flat64, int면 int) 
- 기본 dtype 은 float64임.


[ 배열의 데이터 타입 dtype ]


** Python에서는 허수가 ' j '

** Type code는 Type을 줄여쓴 표기로써, Type code과 Type은 결과가 같다.

** Numpy 와 Python 의 연산자는 크게 차이가 없지만, methods/attributes에서는 NumPy가많다.

(Python - int : 8개 <-> NumPy - int 68개)

< Numpy 와 Python 의 쓰는 법 차이 >
x_py = 123

x_np = np.int64(123)



int (정수형)
i, int_, int32, int64, i8

int_ : 기본 정수 타입, C에서의 long
intc : C에서의 int와 동일
intp : 인덱싱에서 사용하는 정수

dtype
(num : bit)
코드
(num:byte)
설명 예제
int8 i1 부호 있는 8비트 정수형 -128 ~ 127
int16 i2 부호 있는 16비트 정수형 -32768 ~ 32767
int32 i4 부호 있는 32비트 정수형 -2147483648 ~2147483647
int64  i8  부호 있는 64비트 정수형 -9223372036854775808 ~9223372036854775807

 


float (실수형)

f, float_, float 32, float64, f8

dtype
(num : bit)
코드
(num:byte)
설명 예제
float16 f2 실수형 ; 반 정밀도 부동소수점형 부호 1비트
지수 5비트
가수 10비트
float32 f4 실수형; '단 정밀도' 부동소수점형 (Half precision) 부호 1비트
지수 8비트
가수 23비트
float64 f8 실수형; '배 정밀도' 부동소수점형 (Single precision) 부호 1비트
지수 11비트
가수 54비트
float128 f16  실수형; '네배 정밀도' 부동소수점형  (Double precision) 부호 1비트
지수 15비트
가수 112비트

 


complex (복소수형 자료형)
complex_ , complex64, complex128

 

dtype
(num : bit)
코드
(num:byte)
설명 예제
complex_   complex128의 약칭  
complex64   두개의 32비트 부동 소수점으로 표시되는 복소수,
실수부분과 허수부분에 각각의
float64의 자료형
 
complex128   두개의 64비트 부동 소수점으로 표시되는 복소수,실수부분과 허수부분에 각각의
float64의 자료형
 

 

 

str (문자열)
str, U, U32

 

str : 문자열 타입
유니코드 :  U는 유니코드 문자열을 의미
U32(str) : 데이터 용량을 같이 쓴 경우.  32비트 리틀 엔디안 방식으로 언패킹.

* uint에 대해 좀더 자세히? 
파이썬 자료들에서는  U, U32가 문자열 타입의 한종류, 유니코드를 의미하는 것 정도만 알면 된다고 나와있다.
C언어로 구현된 파이썬 라이브러리 Numpy 이다보니, C에서 사용하는 u8,u16,u32,u64의 형태를 확인할 수 있다.

C언어 사용시 char, int, long 등보다는 명확히 몇비트 변수인지 알고 사용 가능.
각 OS(arch) 마다 typedef로 재정의한 변수타입 (int, float은 arch마다 크기 다를 수있음)
uint8,16,32,64의 단위마닫 값차이가 많이 난다.

dtype
(num : bit)
코드
(num:byte)
설명 예제
uint8   Unsinged int형태
unsigned char
0 to 255
uint16   Unsinged int형태
unsigned short, unsigned short int
0 to 65535
uint32   Unsinged int형태
unsigned, unsigned int
0 to 4294967295
uint64   Unsinged int형태 0 to 18446744073709551615

 

*np.dtype('str') 로 축약어를 사용하면 다양한 타입을 지정가능.

예) 

np.dtype('int32') : 32비트 LE 정수, np.int32와 동일
np.dtype('i4') : 4바이트 LE 정수, np.int32와 동일
np.dtype('f8') : 8바이트 LE 실수, np.float64와 동일
np.dtype('>f8') : 8바이트 BE 실수

* 잠깐 ! 리틀 엔디안('<')은 작은수부터 큰수 default 순서 / 빅 엔디안은 ('>')은 큰수부터 작은수로 역순.
정수형의 경우 i{byte}, int{bit}, <i{byte}, >i{byte} 형태 가능 (  '<'는 LE(리틀 엔디안)의미하며 디폴트 )

실수형의 경우 f{byte}, float{bit}, <f{byte}, >f{byte} 형태 가능

 

 

축약어
  • 'b' − boolean
  • 'i' − (signed) integer
  • 'u' − unsigned integer
  • 'f' − floating-point
  • 'c' − complex-floating point
  • 'm' − timedelta
  • 'M' − datetime
  • 'O' − (Python) objects
  • 'S', 'a' − (byte-)string
  • 'U' − Unicode
  • 'V' − raw data (void)

 

 

bool (부울)
?, bool_

 

dtype
(num : bit)
코드
(num:byte)
설명 예제
bool_ ? 바이트 형태로 저장되는 Boolean 타입,
하나의 바이트로 거짓과 참 표현
[True, True, False, False]

 

 


Data Type 객체(dtype)

명령어를 통해 각 배열에 데이터 타입을 지정가능 

 

명령어 :  numpy.dtype(object, align, copy)

- object : data type객체를 통해 변경될 부분 (기존형태)

- copy : data type객체를 복사하여 새로운 객체 생성

 

데이터 형태 지정 : np.array([xx, xx], dtype=np.Type
                            np.array([xx, xx], dtype=np.'Type Code'

                            np.Type([xx, xx])

 

데이터 형태 확인 : object.dtype                                 #object의 자료형을 출력

데이터 형태 변경 :  object.astype(np.Type)              #object에 기존형태, Type에 변경후 형태
                             np.Type(object)                           #object에 기존형태, Type에 변경후 형태

 

 

 


 

[ ndarray 차원 관련 속성 ]

ndim & shape 

 

1차원배열
list = [0, 1, 2, 3]

arr= np.array(list)

print(arr.ndim)          # 1

print(arr.shape)        # (4,)


2차원배열
list = [[0,1,2],[3,4,5]]

arr= np.array(list) 

print(arr.ndim)            # 2

print(arr.shape)          # (2,3)

 

ndarray의 크기속성과 shape조절

arr= np.array([0, 1, 2, 3, 4])

print("arr.shape: {}".format(arr.shape))      # arr.shape: (5,)

print("배열요소의수:{}".format(arr.size))       # 배열요소의수:5

print("배열의길이:{}".format(len(arr)))          # 배열의길이:1 >> 배열안에 리스트 한줄로 되있어서!

 

print( "arr.shape: {}".format(arr.shape) )       # arr.shape: (3,2)

print( "배열요소의수:{}".format(arr.size) )        # 배열요소의수:6

print( "배열의길이:{}".format(len(arr)) )           # 배열의길이:3  >> [0,1] [2,3] [4,]


위의 예제를 통해서 알수 있는 것!  size , len 의 특성
** size 는 단순 길이 이상, 다차원 배열이 품고있는 요소 개수 전체 리턴
** len 은 다차원 배열이어도 한차원 배열만 체크 가능

 

reshape 

reshape을 이용하면 shape 를 바꿀 수가 있다. 배열의 형태를 바꿈.
이때 '-1'을 넣을 경우, '-1'은  원래 배열의 길이와 남은 차원으로 부터 추정


 


[ numpy 의 인덱스와 슬라이싱 ]


x = np.arage(7)

 

인덱싱

 -인덱스로 값을 찾아냄

pritn(x[3])  #3

 

x=np.arage(1,13,1)

x.shape = 3,4

print(x[1:2, 2:3]) # [[5]]

print(x[1: , :2 ]) #[[5 6]

                             [9 10]]

 

x[0] =10 

print(x) # [10 1 2 3 4 5 6]

 

슬라이싱
-인덱스의 값으로 배열의 일부 불러옴.
print(x[1:4]) #[0 1 2 3 4 5 6]
print(x[::2])  #[0 2 4 6]
#[시작:끝:간격 ]

 

Boolean indexing: 배열의 각 요소의 선택 여부를 Boolean mask를 이용하여 지정하는 방식 (mask는 영역선택의미)

예) print( x[x % 2 == 0] ) #[0 2 4 6]

 

Facy indexing : 배열의 각 요소 선택을 Index 배열을 전달하여 지정하는 방식

print(x[[ 1, 3, 5 ]]) #[1 3 5]


조합해서 쓰는 법!

x = np.arange( 1, 13, 1).reshape(3,4)  #1부터 13앞(즉12)까지 1간격으로 나열 -> 그걸 3줄로 4개씩 (행 x 열)

print(x) 

 

# [[ 1 2 3 4]]

    [5 6 7 8]

    [9 10 11 12]]

 


 

2. 데이터 조작 및 분석을 위한 pandas


Pandas의 기본 자료 형태 : Series와 DataFrame

Series 데이터

Series 데이터란 Numpy array가 보강된 형태로

Data index를 가지고 있는 데이터 형식

- 시리즈 데이터를 만드는 방법

import
pandas as pd
series = pd.Series([1,2,3,4], index = ['a', 'b', 'c', 'd'], name="Title")
print(series, "\n")  #이때 "'\n'은 "여러줄 출력 newline  궁금할시 '확장문자 출력' 


##결과
a    1 

b    2

c    3

d    4

Name: Title, dtype: int64

* 추가적 Tip
- pandas의 Series 객체를 만들기 위해, ‘값’과 ‘인덱스’ 매개변수를 각각 넣어주는 방법 있음.

- 딕셔너리를 매개변수로 넣어주는 방법도 있음.


DataFrame 데이터프레임

시리즈 데이터는 하나의 컬럼 값으로 이루어진 반면 

데이터 프레임 여러 개의 컬럼 값을 가질 수 있다.

여러 개의 시리즈 데이터를 이용하여 데이터 프레임을 만듦


# 먼저 population 과 gdp의 시리즈 데이터 생성을 마친후,
아래와 같이 써주면 2개의 시리즈값이 들어간 데이터 프레임 생성.

country = pd.DataFrame({   
'population': population,
'gdp':gdp

#데이터 프레임의 인덱스와 컬럼값 확인 하는 방법

print(country.index)
print(country.columns)

 


pandas에서 조작 및 분석 하려면..

1. 딕셔너리 생성 data{key:value}
2. 시리즈 만듦  seris([1,2,3,4])
3. 데이터프레임 ( 인덱스 / 시리즈 데이터 로 구성된 표!) 만들기



< 예시를 통해 설명하는 pandas 데이터 조작 및 분석 >

1. 딕셔너리 생성 data{key:value} 

population_dict = {
    'korea': 5180,
    'japan': 12718,
    'china': 141500,
    'usa': 32676
}

2. Series 만들기
DataFrame 생성 가능
> 국가별 인구 수 데이터를 시리즈로 만들 country라는 변수에 저장

dict = {
'korea' : 5180,
'japan' : 12718,
'china' : 141500,
'usa' : 32676
}
country = pd.Series(dict)
print(country)


##결과

korea      5180

japan     12718

china    141500

usa       32676 

dtype: int64


-----------------

data = {

    'korea': 169320000,
    'japan': 516700000,
    'china': 1409250000,
    'usa': 2041280000,

}


3. 데이터프레임 만들기

country = pd.DataFrame(data)   #표형태로 생성됨
country = country.set_index('country')  #컨트리(데이터프레임)는 인덱스를 세팅할때 컨트리(키)를 컬럼(표속성)으로 사용하겠다.

 

DataFrame (표) 속성을 확인하는 방법

print(country.shape). - 행 x 열

print(country.size) - 전체 갯수 (행,열의 곱한값) 

print(country.ndim)  - 열 = N(차원)

print(country.values)  - 컬럼의 내용값 ( 가로세로 컬럼의 속성 제외)

 

 

country.to_csv("./country.csv")  -csv 파일로 저장

country.to_excel("country.xlsx") -xlsx 파일로 저장

country = pd. read_csv("./country.csv")  -csv 파일 불러오기 

country = pd.read_excel("country.xlsx") -xlsx 파일 불러오기


** read_csv( )  /  read_table( )  /  read_fwf( )  가  있다.
** read_csv( )  /  read_table( )  은 필드 구분 문자(delimiter)가 콤마( , )인지, 탭( \t ) 인지 차이
** 

series = pd.Series([1,2,3,4], index = ['a', 'b', 'c', 'd'], name="Title")


country.index.name = "country"      #인덱스에 이름 지정

country.columns.name = "Info"       #컬럼에 이름 지정

 

print(country.index)  #인덱스 출력

## 결과
Index(['korea', 'japan', 'china', 'usa'], dtype='object')

 

 


데이터 선택 및 변경하기

 

[ pandas 의 인덱스와 슬라이싱 ]


1. ' .loc  '
명시적인 인덱스를 참조하는 인덱싱/ 슬라이싱

인덱싱

 -인덱스로 값을 찾아냄

country.loc['china']     #인덱싱

슬라이싱
-인덱스의 값으로 배열의 일부 불러옴.

country.loc['japan':'korea', :'population']      #슬라이싱

 

 

2. ' .iloc  '
파이썬스타일의 정수 인덱스 인덱싱/슬라이싱

 

인덱싱

 -인덱스로 값을 찾아냄

country.iloc[0]   #인덱싱

슬라이싱
-인덱스의 값으로 배열의 일부 불러옴.

country.iloc[1:3, :2]      #슬라이싱


[ pandas 의 데이터 선택 _ 컬럼 선택 ]

컬럼명 활용하여 DataFrame에서 데이터 선택

 

예시) 

country

country['gdp']          # 시리즈 선택

country[['gdp']]        # 데이터 프레임 선택

 

#시리즈 데이터
korea      5180

japan     12718

china    141500

usa       32676 

dtype: int64

 

#데이터 프레임 

              population        
korea        5180   
japan       12718   
china      141500  
usa         32676  

 


 

[ pandas 의 조건이 충족되는 값 추출하기 ]

 

데이터 프레임에서,
각 컬럼마다 조건을 충족하는 값만 추출할 수 있다.

- Numpy의 마스킹 연산처럼 조건식을 직접 쓰는 방법

- query() 함수를 이용하는 방법

** Masking연산이나 query 함수를 활용하여 조건에맞는 DataFrame행 추출가능

 

예시)
A, B를 가진 2차원의 데이터프레임을 생성하여 df에 저장된 상태일때.


1. A컬럼 값이 0.5보다 작고 B컬럼 값이 0.3보다 큰 값들을 마스킹 연산을 활용하여 출력

print( df[ ( df['A']<0.5 ) & ( df['B']>0.3 ) ] )
#A의 컬럼 값 df['A']
#B의 컬럼 값 df['B']
#마스킹 연산은 df[ (컬럽값1) & (컬럼값2) ]

 

2. 위와 같은 조건의 값들을 query 함수를 활용하여 출력
print( df.query("A<0.5 and B>0.3") )

#A의 컬럼 값 A
#B의 컬럼 값 B
#마스킹 연산은 df.query(컬럼값1 and 컬럼값2))



[ pandas 의 새로운 컬럼 추가하기 ]

 

 기존 데이터프레임 값을 활용하여 새로운 컬럼을 생성하는 법

 

- Series도 numpy array처럼 연산자 활용가능

 

 

1. country의 두 컬럼을 이용하여 새로운 컬럼을 만들기
- 1인당 GDP(gdp per capita)를 데이터 프레임에 추가
- 1인당 GDP는 gdp를 population으로 나누어 얻음

 

import numpy as np
import pandas as pd

# 시리즈 2개 (GDP,인구수)의 데이터프레임을 생성
population = pd.Series({'korea': 5180,'japan': 12718,'china': 141500,'usa': 32676})
gdp = pd.Series({'korea': 169320000,'japan': 516700000,'china': 1409250000,'usa': 2041280000})
print("Country DataFrame")

country = pd.DataFrame({"population" : population,"gdp" : gdp})
print(country)

# 데이터프레임에 gdp per capita 칼럼을 추가
gdp_per_capita = country['gdp']/country['population'] # gdp % population = 1인당 GDP
country['gdp per capita'] = gdp_per_capita

#출력
print( country['gdp per capita'] )

[ pandas 의 데이터 추가, 수정 ]

 

- 리스트로 추가

- 딕셔너리로 추가

 

df = pd.DataFrame(columns=['이름','나이','주소'])          #데이터프레임 생성

df.loc[0] = ['길동', '26', '서울']                                          #리스트로 데이터 추가

df.loc[1] = {'이름':'철수', '나이':'25', '주소':'인천'}              #딕셔너리로 데이터 추가

df.loc[1, '이름'] = '영희'                                                     #명시적 인덱스 활용하여 데이터수정

 

 

- NaN값으로 초기화된 새로운 컬럼추가

 

df['전화번호'] = np.nan

# 새로운 컬럼 추가 후 초기화

 

df.loc[0, '전화번호']='01012341234'

# 명시적 인덱스 활용하여 데이터수정

 

 

- 컬럼삭제 - DataFrame에서 '컬럼 삭제' 후 '원본 변경'


.drop('컬럼이름',열 or 행, 변경여부)

df.drop('전화번호', axis= 1, inplace= True)       

 

# .drop은 컬럼삭제  

 

#axis = 1 : 열방향  /  axis = 0 : 행방향

#inplace= True : 원본변경  /  inplace=False : 원본변경X


 

index 값 기준으로 정렬하기 

 

- axis = 0: 행인덱스기준정렬(Default오름차순)

df = df.sort_index(axis= 0)

 

-axis = 1: 열인덱스기준내림차순정렬

df.sort_index(axis= 1, ascending= False)

 

column 값 기준으로 정렬하기 

 

- col1 컬럼 기준 정렬 defalut 오름차순

df.sort_values('col1',ascending= True)

 

-col1컬럼기준내림차순정렬

df.sort_values('col1', ascending= False)

 

-col2컬럼기준오름차순정렬후col2컬럼기준내림차순정렬

df.sort_values(['col2', 'col1'], ascending= [True, False])


[ 데이터 프레임 분석용 함수 ]

 

집계함수
집계함수는 많은 데이터 값을 입력받아, 이를 요약하는 하나의 값을 반환하는 기능
count(), max(), min(), sum(), mean() 

 

count

데이터 프레임 분석용 함수 count

메서드 활용하여 데이터개수 확인가능 (Default : NaN값제외)

max, min

메서드활용하여최대, 최소값확인가능

(Default : 열기준,NaN값제외)

 

sum,mean

메서드활용하여 합계및평균계산

(Default : 열기준,NaN값제외)

 

axis, skipna

인자활용하여합계및평균계산

(행기준,NaN값포함시)

 

NaN

NaN값이존재하는column의평균구하여NaN값대체

 

B_avg= df['math'].mean()print(B_avg)

 

#25.0# NaN값대체

df['math'] = df['math'].fillna(B_avg)

 

# 평균

df.mean(axis = 1, skipna= False)

 

 

import numpy as np
import pandas as pd

data = {
    'korean' : [50, 60, 70],
    'math' : [10, np.nan, 40]
}
df = pd.DataFrame(data, index = ['a','b','c'])
print(df, "\n")

# 각 컬럼별 데이터 개수

col_num = df.count(axis = 0)
print(col_num, "\n")

# 각 행별 데이터 개수

row_num = df.count(axis = 1)
print(row_num, "\n")

# 각 컬럼별 최댓값

col_max = df.max()
print(col_max, "\n")

# 각 컬럼별 최솟값

col_min = df.min()
print(col_min, "\n")

# 각 컬럼별 합계

col_sum = df.sum()
print(col_sum, "\n")

# 컬럼의 최솟값으로 NaN값 대체

math_min = df['math'].min()
df['math'] = df['math'].fillna(math_min)
print(df, "\n")

# 각 컬럼별 평균

col_avg = df.mean()
print(col_avg, "\n")

 

분석용 함수
그룹으로 묶기(1) - groupby()

groupby() 함수를 이용하면 키 값을 기준으로 그룹으로 묶음\

간단한 집계를 넘어서서 조건부로 집계하고 싶은경우

 

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'key': ['A', 'B', 'C', 'A', 'B', 'C'],
    'data1': [1, 2, 3, 1, 2, 3],
    'data2': [4, 4, 6, 0, 6, 1]
})
print("DataFrame:")
print(df, "\n")

# groupby 함수를 이용해봅시다.
# key를 기준으로 묶어 합계를 구해 출력해보세요.

print(df.groupby('key').sum())

# key와 data1을 기준으로 묶어 합계를 구해 출력해보세요.

print(df.groupby(['key','data1']).sum())

 

분석용 함수
그룹으로 묶기(2) - aggregate() 함수

키값을 기준으로 그룹으로 묶은 결과의 요약 통계량을 구함.
결과값 또한 데이터프레임으로 반환되어 한 눈에 보기 편리.

groupby를통해서집계를한번에계산하는방법

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'key': ['A', 'B', 'C', 'A', 'B', 'C'],
    'data1': [0, 1, 2, 3, 4, 5],
    'data2': [4, 4, 6, 0, 6, 1]
})
print("DataFrame:")
print(df, "\n")


#agregate 메소드에 함수를 매개변수로 넣어줄 때,

#df.groupby('key').aggregate([min, np.median, max])

#min, max, mean, count 등의 특정 함수들은 문자열 형태로 넘겨주실 수 있습니다.

#df.groupby('key').aggregate(['min', np.median, 'max'])



# aggregate를 이용하여 요약 통계량을 산출해봅시다.


# 데이터 프레임을 'key' 칼럼으로 묶고, data1과 data2 각각의 최솟값, 중앙값, 최댓값을 출력하세요.


print(df.groupby('key').aggregate([min, np.median, max]))

# 데이터 프레임을 'key' 칼럼으로 묶고, data1의 최솟값, data2의 합계를 출력하세요.

print(df.groupby('key').aggregate({'data1':min, 'data2':sum}))

 

filter

그룹으로묶기(3)

groupby를 통해서 그룹속성을 기준으로 데이터필터링

 

def filter_by_mean(x):

       return x['data2'].mean() > 3

df.groupby('key').mean() #1번

df.groupby('key').filter(filter_by_mean)  #2번

 

apply, lambda

그룹으로묶기(4)

groupby를통해서묶인데이터에함수적용

 

def filter_by_mean(x):

       return x['data2'].mean() > 3

df.groupby('key').mean()   #1번

df.groupby('key').filter(filter_by_mean)  #2번

 

get_group

그룹으로묶기(4)

groupby로묶인데이터에서key값으로데이터를가져올수있다

 

df = pd.read_csv("./univ.csv")   #상위5개데이터

df.head()     #데이터추출

df.groupby("시도").get_group("충남")

len(df.groupby("시도").get_group("충남")) #94

 

 

728x90
반응형

댓글