새싹 인공지능 응용sw 개발자 양성 교육 프로그램 나예진 강사님 수업 정리 글입니다. (나예진 강사님 이메일: nayejin11@gmail.com)
목차
1. lambda
2. 패키지, 모듈, 함수의 관계도
3. numpy
4. pandas
inline function, def라고 하는 명령어 없이 간단하게 정의해서 사용할 수 있다.
def add(a, b): #a,b 지역변수
return a+b
def return_length(s):
return len(s)
#lambda함수로 바뀌면
f = lambda a, b: a+ b
print(add(3, 5))
print(f(3, 5))
-> 8
8
lambda x: x + 10
-> <function __main__.<lambda>(x)>
# 익명 함수이기때문에 람다식을 변수에 할당해야 한다.
plus_ten = lambda x: x + 10
plus_ten(1)
-> 11
#아래 리스트의 원소들을 원소들의 길이에 따라 정렬하고 싶은 경우엔 어떻게 해야할까?
strings = ['yoon', 'kim', 'jessica', 'jeong']
#strings.sort() #alphabetical order로 정렬됩니다. 사전순 정렬
strings.sort(key=lambda s:lens(s)) #len(s)은 알파벳 갯수의 기준으로 정렬된다.
strings
-> ['kim', 'yoon', 'jeong', 'jessica']
#수학 계산
import math
#절대값, 올림, 내림
print(abs(-3))
print(math.ceil(3.5))
print(math.floor(3.5))
#sin, cos
print(math.sin(1))
print(math.cos(1))
->3
4
3
3
0.8414709848078965
0.5403023058681398
#복권 숫자를 만들어 봅시다.
import random
random.sample(range(1, 46), 7)
#range = 1~46 숫자를 가지고 있는 집합, sample은 7개를 뽑아라,
몇 개 중에 = ragne , 몇 개를 뽑아라 = sample
-> [1, 35, 11, 14, 3, 31, 40]
#다양한 사전들을 써봅시다.
from collections import defaultdict
from collections import OrderedDict
D = defaultdict(int)
D2 = OrderedDict()
D2['z'] = 26
D2['a'] = 1
D2['c'] = 3
D2['d'] = 5
D2['j'] = 14
D2['b'] = 2
D2
->
OrderedDict([('z', 26), ('a', 1), ('c', 3), ('d', 5), ('j', 14), ('b', 2)])
#짝수만을 출력하고 싶을 때
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even= []
for i in mylist:
if i % 2 == 0:
even.append(i)
print(even)
-> [2, 4, 6, 8, 10]
🧠사전 도서관 비유
도서관 = 패키지(=라이브러리)
사전 = 모듈
단어 = 함수
사전 안의 단어 하나하나 = 함수(단어)
단어 하나만은 의미가 없고 어떻게 사용할 때 의미가 있다.
함수들의 집합, 쓰고 자 하는 함수들이 모아져 있는 것 = 모듈(사전)
(도서관) = 패키지 = 라이브러리
import 왜 할까? 다른 사람이 이미 만들어 놓은 좋은 모듈을 우리가 쉽게 가져다 쓸 수 있기 때문이다.
import하는 방법 : py(파이썬 파일 확장자)로 된 파일을 우리는 모듈이라고 한다. imprort구문을 통해 파일을 불러 올 수 있다.
import pandas
# 위의 코드는 pandas라는 모듈은 우리가 불러오겠다라는 의미이며,
이미 colab에서 유명한 모듈은 설치가 되어 있는 상태이기 때문에,
우리가 따로 설치할 필요없이 가져올 수 있다.
패키지는 모듈의 그룹이다.
🧠직박구리폴더 예시
직박구리 폴더에 파일1이 들어있다.
직박구리 폴도 = 패키지
파일1 = 모듈
from 패키지 import 모듈
from 직박구리 import 파일1
from pandas import DataFrame
#pandas라는 패키지 안에 Dataframe의 모듈을 가져와라
별칭(alias)지어주기
pandas라는 패키지 이름이 너무 길어서 약어로 줄여쓸 수 있다. as사용
앞으로 자주 사용할 패키지, 모듈 미리보기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sesaborn as sns
#numpy: 과학 계산을 위한 패키지
#pandas: 데이터 분석을 할 때 가장 많이 쓰이는 패키지
#matplotlib: 시각화를 위한 패키지
#seaborn: 시각화를 위한 패키지(matplotlib을 더 쉽게 사용할 수 있도록 도와주는 패키지)
numerical python
기능
numerical computing: 컴퓨터가 실수값을 효과적으로 계산가능
vector arithmetic: 백터 연산 = 데이터가 벡터로 표현되기 때문 = 행열계산 = 데이터 타입이 행열 형태로 되어야 한다.
-> 데이터 분석할 때 사용되는 pandas와 matplotlib의 기반으로 사용된다.
numpy에서 기본적으로 array라는 단위로 데이터를 관리하며 이에 대해 연산을 수행한다.
numpy vs list
numpy.array | list |
---|---|
한 가지 자료형만 허용 | 여러 가지 자료형 허용 |
내부 배열에서 원소 개수 같아야 함 | 내부 배열 내 원소 개수 달라도 됨 |
선언할 때 크기 지정하고 변경 불가(정적 할당) | 계속 크기가 변화 가능(동적 할당) |
#list출력
list_data = [1, 2, 3]
print(list_data)
-> [1, 2, 3]
#numpy출력
import numpy as np
list_data = [1, 2, 3]
array = np.array(list_data) # =numpy형태로 바꾸는 것
print(array)
print(array.size)
print(array.dtype)
iprint(array[2])
-> [1, 2, 3]
3
int32
3
#list 연산
t1 = (1, 2, 3)
t2 = (4, 5)
t1 + t2
-> (1, 2, 3, 4, 5)
#numpy 연산
import numpy as np
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([3, 4, 5, 6, 7])
arr1 + arr2
->array([ 4, 6, 8, 10, 12])
#numpy 라이브러리를 불러옵니다.
import numpy as np
#파이썬 리스트 선언
data = [1, 2, 3, 4, 5]
data, type(data)
-> ([1, 2, 3, 4, 5], list)
#파이썬 2차원 리스트(행렬) 선언
data2 = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
data2
-> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
#파이썬 list를 numpy array로 변환
arr1 = np.array(data)
print(type(arr1)) # = <class 'numpy.ndarray'> , 이제 행렬이 되었다.
arr1, type(arr1) #numpy.ndarray : ndarray(n-dimensional array)
# numpy array를 만드는 방식의 대부분은 파이썬 리스트를 np.array로 변환하는 방식
arr1.shape #shape = shape이 어떻게 생겼니 알려줌
# np.array.shape은 np.array의 크기를 알려줌
-> <class 'numpy.ndarray'>
(5,)
arr2 = np.array(data2)
print(arr2)
print(type(arr2))
arr2.shape #index값을 사용하지 않고 좌표값을 사용한다.
-> [[ 1 2 3]
[ 4 5 6]
[ 7 8 90]]
<class 'numpy.ndarray'>
(3, 3)
print("arr2의 nidm : ", arr2.ndim) #arr2의 차원
print("arr2의 shape : ", arr2.shape) #arr2의 행, 열의 크기
print("arr2의 size: ", arr2.size) #arr2의 행 x 열
print("arr2의 dtype : ", arr2.dtype) #arr2의 원소의 타입
print("arr2의 itemsize : ", arr2.itemsize) #arr2의 원소의 사이즈
print("arr2의 nbytes : ", arr2.nbytes) #itemsize * size
-> arr2의 nidm : 2
arr2의 shape : (3, 3)
arr2의 size: 9
arr2의 dtype : int64
arr2의 itemsize : 8
arr2의 nbytes : 72
# 0이 5개 있는 array
np.zeros(5)
-> array([0., 0., 0., 0., 0.])
# 0이 3x3인 array
np.zeros((3, 3))
-> array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
# 1이 3개 있는 array
np.ones(3)
-> array([1., 1., 1.])
# 1이 2x2인 array
np.ones((2, 2))
-> array([[1., 1.],
[1., 1.]])
# 0부터 9까지 숫자를 자동으로 생성한 array
np.arange(10)
-> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 10부터 99까지 숫자를 자동으로 생성한 array
np.arange(10, 100) # python range 함수와 동일한데, np.array 생성까지 자동으로 해줍니다.
->array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99])
numpy array를 쓰는 가장 큰 이유는 vector처럼 사용할 수 있기 때문
ex)arr1 = np.array([1, 2, 3, 4, 5]) --> (1, 2, 3, 4, 5)
방향성 있는 숫자들의 집합. 주로 배열이라고 말한다.
방향성 있는 숫자들의 집합이라서 index의 개념이 나온 것이다.
대부분의 데이터 분석 라이브러리들은 벡터를 사용하는데, 그 벡터가 바로 numpy array로 표현되기 때문입니다.
데이터 분석은 99.9% 데이터를 벡터로 표현하여 분석하기 때문에, 이 특징은 굉장히 중요합니다.
벡터 == numpy array
# v1 = (1, 2, 3), v2 = (4, 5, 6) 벡터 2개 생성하기.
v1 = np.array((1, 2, 3))
v2 = np.array((4, 5, 6))
type(v1), type(v2)
>> (numpy.ndarray, numpy.ndarray)
# vector addition
v1 + v2
>>array([5, 7, 9])
# vector subtraction
v1 - v2
>>array([-3, -3, -3])
# (not vector operation) elementwise multiplication
v1 * v2
>>array([ 4, 10, 18])
# (not vector operation) elementwise division
v1 / v2
>>array([0.25, 0.4 , 0.5 ])
# dot product
v1 @ v2 # 1x4 + 2x5 + 3x6 = 32
>>32
서로 크기가 다른 numpy array를 연산할 때, 자동으로 연산을 전파(broadcast)해주는 기능. 행렬곱 연산을 할 때 편리하다.
arr1 = np.array([[1, 2, 3],
[4, 5, 6]])
arr1.shape
>> (2, 3) # 2행 3열
arr2 = np.array([7, 8, 9])
arr2.shape
>>(3,) #
# 2개의 array를 더해보면?
arr1 + arr2 # [1, 2, 3] + [7, 8, 9] // [4, 5, 6] + [7, 8, 9]
>>array([[ 8, 10, 12],
[11, 13, 15]])
# 2개의 array를 곱해보면? (**)
arr1 * arr2 # [1, 2, 3] * [7, 8, 9] // [4, 5, 6] * [7, 8, 9]
# [1, 2, 3] X [7]
# [4, 5, 6] [8]
# [9]
>>array([[ 7, 16, 27],
[28, 40, 54]])
# arr1에 10을 곱해보면?
arr1 * 10 # vector scalar multiplication
>>array([[10, 20, 30],
[40, 50, 60]])
# arr1을 제곱해보면?
arr1 * arr1
>>array([[ 1, 4, 9],
[16, 25, 36]])
numpy array는 하나의 함수를 모든 원소에 자동으로 적용해주는 Universal Function이라는 기능을 제공한다. 이 덕분에 모든 원소에 대해 같은 작업을 처리할 때 엄청나게 빠른 속도를 낼 수 있다.
arr1 = np.array([1, 2, 3])
arr1 = arr1 / 1
#arr1.dtype
# 모든 원소를 역수를 취하려면 어떻게 해야할까?
1 / arr1 # 각 원소에 1 / 라는 operation을 모두 적용하는 연산이 됩니다
>>array([1. , 0.5 , 0.33333333])
# 모든 원소에 2를 더하려면 어떻게 해야할까?
arr1 + 2
>>array([3., 4., 5.])
arr1 = np.arange(10)
arr1
>>array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 첫번째 원소
arr1[0]
>>0
# 마지막 원소
arr1[-1]
>>9
# 앞에서부터 원소 3개 slicing
arr1[:3]
>> array([0, 1, 2])
arr2 = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
arr2
>>array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
# arr2의 2, 3 원소 = 7
arr2[1, 2]
>> 7
# arr2의 세번째 columnm (3, 7, 11)
arr2[:, 2] # arr2에 있는 모든 row에 대해서 3번째 원소를 indexing --> numpy array
# arr2[0, 2]
# arr2[1, 2]
# arr2[2, 2]
>>array([ 3, 7, 11])
# arr2의 두번째 row
#arr2[1]
arr2[1, :] # arr2에 있는 두번째 row에 대해서 모든 원소를 indexing --> numpy array
>> array([5, 6, 7, 8])
mask = np.array([1, 0, 0, 1, 1, 0, 0])
mask
>>array([1, 0, 0, 1, 1, 0, 0])
data = np.random.randn(7, 4)
data
>>array([[ 1.92952526, 0.16811586, -0.54101152, 0.01775069],
[-0.01501298, -0.49388391, -0.73565307, 0.07600854],
[-0.01667803, 1.89936971, -0.04026871, 0.90275741],
[ 2.02695639, 0.0905108 , -0.33656963, -0.44864434],
[-0.05168743, 0.69968886, -1.85008029, -1.48106361],
[ 0.53789872, 1.30805042, 1.27204837, 0.02936776],
[ 0.82310049, -0.27940677, -0.8763139 , -0.474734 ]])
data.shape
>>(7, 4)
# mask 만들기
masked_data = (mask == 1)
masked_data
>>array([ True, False, False, True, True, False, False])
# 위에서 생성한 data에 mask를 적용해본다.
data[masked_data, :]
>>array([[ 1.92952526, 0.16811586, -0.54101152, 0.01775069],
[ 2.02695639, 0.0905108 , -0.33656963, -0.44864434],
[-0.05168743, 0.69968886, -1.85008029, -1.48106361]])
# 마스크를 0으로 바꿔본다.
data[mask == 0, :]
>> array([[-0.01501298, -0.49388391, -0.73565307, 0.07600854],
[-0.01667803, 1.89936971, -0.04026871, 0.90275741],
[ 0.53789872, 1.30805042, 1.27204837, 0.02936776],
[ 0.82310049, -0.27940677, -0.8763139 , -0.474734 ]])
# fancy indexing을 이용해서 masking
#data[:, 0] < 0
data[:, 0] < 0 # 7 x 1의 mask == 첫번째 column의 원소중에 0보다 작은 원소들의 위치가 True.
>> array([False, True, True, False, True, False, False])
# fancy indexing의 또 다른 방법
data[data[:, 0]<0, 0]
>> array([-0.01501298, -0.01667803, -0.05168743])
data < 0
>>array([[False, False, True, False],
[ True, True, True, False],
[ True, False, True, False],
[False, False, True, True],
[ True, False, True, True],
[False, False, False, False],
[False, True, True, True]])
data[data < 0] = 0 # 2차원 data에서 첫번째 column에 0보다 작은 원소들을 0으로 치환해주세요.
data
>> array([[1.92952526, 0.16811586, 0. , 0.01775069],
[0. , 0. , 0. , 0.07600854],
[0. , 1.89936971, 0. , 0.90275741],
[2.02695639, 0.0905108 , 0. , 0. ],
[0. , 0.69968886, 0. , 0. ],
[0.53789872, 1.30805042, 1.27204837, 0.02936776],
[0.82310049, 0. , 0. , 0. ]])
x = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
x
>>array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# x를 3x3 행렬로 변형합니다.
x1 = np.arange(1, 10).reshape(3, 3)
x1
>>array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
x == x1
>>array([[ True, True, True],
[ True, True, True],
[ True, True, True]])
# (1, 2, 3)을 transpose 해봅니다.
x2 = np.array([1, 2, 3]).reshape(3, 1) # row vector -> column vector
x2
>>array([[1],
[2],
[3]])
pandas는 정형 데이터 처리에 특화되어 있다. pandas 역시 다양한 머신러닝 라이브러리들에 의존성을 가지고 있다. 간단하게 생각하면, python에서 excel의 기능을 사용할 수 있게 됩니다.
-> pandas에서column을 지정할 수 있다.
pandas 라이브러리에서 기본적으로 데이터를 다루는 단위는 dataframe이다.
pandas의 기본 자료구조(series, dataframe)
#pandas 라이브러리를 불러옵니다. pd를 약칭으로 사용합니다.
import pandas as pd #data 하나를 series라고 한다. series의 모임이 곧 datagrame이 된다. #dataframe은 2차원 테이블이고, 테이블의 한 줄을 series라고 한다.
import numpy as np
print(pd.__version__)
>>1.3.5
#s는 1, 3, 5, np.na, 6, 8을 원소로 가지는 pandas.series
s = pd.Series([1, 3, 5, np.nan, 6, 8])
s
>>0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
#20210101부터 6일간의 날짜 범위를 생성하는 pandas.date_range
dates = pd.date_range('20210101', periods = 6)
dates
>>DatetimeIndex(['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04',
'2021-01-05', '2021-01-06'],
dtype='datetime64[ns]', freq='D')
index값 확인= df.index
df.index
>>DatetimeIndex(['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04',
'2021-01-05', '2021-01-06'],
dtype='datetime64[ns]', freq='D')
df.columns
>>Index(['A', 'B', 'C', 'D'], dtype='object')
#dataframe에 대한 전체적인 요약정보를 보여줍니다. index, columns, null/not-null/dtype/memory usage가 표시됩니다.
df.info()
>><class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 6 entries, 2021-01-01 to 2021-01-06
Freq: D
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 A 6 non-null float64
1 B 6 non-null float64
2 C 6 non-null float64
3 D 6 non-null float64
dtypes: float64(4)
memory usage: 240.0 bytes
#pandas datagrame은 column 이름을 이용하여 기본적인 indexing이 가능
#column A를 indexing
df["A"] #dataframe에 바로 indexing을 사용하면, column을 찾습니다.
# == "key"를 indexing. == "key" == "column"
# df["2021-01-01"]
>> 2021-01-01 -2.335166
2021-01-02 1.863117
2021-01-03 2.053549
2021-01-04 0.357407
2021-01-05 -0.358786
2021-01-06 -0.037734
Freq: D, Name: A, dtype: float64
#특정날짜를 통한 indexing
df.loc['2021-01-03'] #pd.series
>>A 2.053549
B -0.107848
C -0.420052
D -1.373987
Name: 2021-01-03 00:00:00, dtype: float64
#특정 위치를 통한 indexing, 숫자를 가져올 수 있다
df.iloc[2]
>>A 2.053549
B -0.107848
C -0.420052
D -1.373987
Name: 2021-01-03 00:00:00, dtype: float64
df.loc['2021-01-02']
>>A 1.863117
B -0.622961
C -0.163947
D 0.454989
Name: 2021-01-02 00:00:00, dtype: float64
#df.loc는 특정값을 기준으로 indexing합니다 (key - value)
#2013-01-01값을 가지는 row을 가져옵니다.
df.loc[dates[0]] #df.loc[]
>> A -2.335166
B 0.171624
C -1.117064
D 1.006057
Name: 2021-01-01 00:00:00, dtype: float64
df['A'] > 0
>>2021-01-01 False
2021-01-02 True
2021-01-03 True
2021-01-04 True
2021-01-05 False
2021-01-06 False
Freq: D, Name: A, dtype: bool
df.loc[:, 'A'] > 0
>> 2021-01-01 False
2021-01-02 True
2021-01-03 True
2021-01-04 True
2021-01-05 False
2021-01-06 False
Freq: D, Name: A, dtype: bool
df[df["A"] > 0]["B"] #A값이 0보다 큰 B값을 뽑을 꺼야
>> 2021-01-02 -0.622961
2021-01-03 -0.107848
2021-01-04 -0.670047
Freq: D, Name: B, dtype: float64
df['A'][df["A"]>0]
>>2021-01-02 1.863117
2021-01-03 2.053549
2021-01-04 0.357407
Freq: D, Name: A, dtype: float64