
시작하기 전에 import 하기
import numpy as np import pandas as pd import numba
apply 메서드는 DataFrame에 함수를 적용하여 반환하는 메서드 입니다.
함수에 전달되는 객체는 Seires형식이며 DataFrame의 index(axis=0)이냐 columns(axis=1)이냐에 따라 다릅니다.
최종반환 유형은 적용된 함수에 따라 정해지지만 result_type을 지정하여 변경이 가능합니다.
기본 사용법
df.apply(func, axis=0, raw=False, result_type=None, args=(), kwargs)
function : 각 행이나 열에 적용할 함수 입니다.
axis : {0 : Index / 1 : columns} 함수를 적용할 축 입니다.
row : {True : ndarray / False : Series} 함수에 전달할 축의 형식입니다.
True면 ndarray형태로 전달하고 False면 Series형태로 전달합니다. 기본적으로 Series입니다.
result_type : {expand / reduce / broadcast} 반환값의 형태를 결정합니다. expand이면 배열 형태를
기준으로 열을 확장합니다.(기본 인덱스로), reduce인 경우는 그대로 Serise형태로 반환합니다.
broadcase인 경우 기존 열 형식대로 확장하여 반환합니다.(열의 수가 같아야합니다.)
먼저, 간단한 3x3 객체를 하나 생성하겠습니다.
col = ['col1','col2','col3'] row = ['row1','row2','row3'] data = [[1,2,3],[4,5,6],[7,8,9]] df = pd.DataFrame(data=data,index=row,columns=col) print(df)
func의 성질에 따른 차이
func항목이 np.sqrt처럼 축에대해 계산할 수 없는 형식이라면 아래와 같이 각 요소에 적용됩니다.
(실행 예시1)print(df.apply(np.sqrt))
np.sum처럼 축에대해 적용이 가능한경우라면 축 기준으로 연산을 수행합니다.
(실행 예시2)print(df.apply(np.sum))
axis에 따른 차이
axis가 0인경우 Index(행)에 대해 연산을 수행하고, 1인경우는 columns(열)에 대해 연산을 수행합니다.
(실행 예시1)print(df.apply(np.prod,axis=0))
(실행 예시2)print(df.apply(np.prod,axis=1))
result_type에 따른 차이
먼저 lamba를 사용하여 기존 DataFrame에 [1,2,3]객체를 apply해보겠습니다.
(실행 예시1)print(df.apply(lambda x : [1,2,3]))
result_type = 'expand'인 경우
func를 기준으로 확장하여 columns를 지정하게 되는것을 확인할 수 있습니다.
(실행 예시2)print(df.apply(lambda x : [1,2,3], axis=1,result_type='expand'))
result_type = 'reduce'인 경우
func를 기준으로 축소하여 columns없이 Series 객체로 반환하는것을 확인할 수 있습니다.
(실행 예시3)print(df.apply(lambda x : [1,2,3], axis=1,result_type='reduce'))
result_type = 'broadcast'인 경우
func를 기준으로 확장하되, columns는 기존 DataFrame의 것을 사용하는것을 확인할 수 있습니다.
(실행 예시4)print(df.apply(lambda x : [1,2,3], axis=1,result_type='broadcast'))
applymap 메서드는 객체의 각 요소에 함수를 적용하는 메서드입니다.
즉, apply메서드와는 다르게 DataFrame의 각 요소 하나하나에 함수를 적용하여 스칼라 값을 반환합니다.
기본 사용법
df.apply(func, axis=0, raw=False, result_type=None, args=(), kwargs)
func : 단일 값을 반환하는 함수 입니다.
na_action : {None / 'ignore} NaN의 무시 여부입니다. 'ignore'이면 NaN을 함수로 전달하지 않습니다.
먼저, pd.NA가 포함된 간단한 3x3 객체를 하나 생성하겠습니다.
col = ['col1','col2','col3'] row = ['row1','row2','row3'] data = [[1,2,3],[4,5,6],[7,pd.NA,9]] df = pd.DataFrame(data=data,index=row,columns=col) print(df)
applymap의 적용
함수 적용시 각 요소에 대해 함수의 연산이 되는것을 확인할 수 있습니다.print(df.applymap(lambda x : x**2,na_action='ignore'))
pipe 메서드는 함수를 연속적으로 사용할 때 유용한 메서드입니다.
특히 함수가 인수를 사용할 때 pipe 메서드를 사용하면 보다 직관적으로 적용할 수 있습니다
기본 사용법
df.pipe(func, args, kwargs)
func : 함수입니다.
arg : 함수의 인수입니다.
kwargs : dict 형태의 함수의 인수입니다.
만약 함수 3개가 아래와 같이 있다고 해봅니다.
f1(data, arg1), f2(data, arg1, arg2, f3(data, arg3)
f1 > f2 > f3 순서로 포함되게 함수를 사용한다고 하면 아래와 같이 함수를 사용해야 합니다.
df=f1( f2( f3( data,arg3='c' ),arg2='b1',arg3='b2' ),arg1='a' )
이는 어떤 arg가 어떤함수인지 직관적으로 볼 수 없습니다. 이때, pipe함수를 사용할 수 있습니다.
df=data.pipe(f3, arg3='c').pipe(f2, arg2='b1', arg3='b2').pipe(f3, arg3='c')
먼저 입력 데이터를 정의해보겠습니다
org_data = pd.DataFrame({'info':['삼성전자/3/70000','SK하이닉스/2/100000']}) print(org_data)
그리고 함수 두개를 만들어보겠습니다.
code_name(data) 는 (종목명/수량/가격)형태인 문자열 data를 입력받아서 각각으로 분리하고 수량과 가격의 dtype을 int로 변경하는 함수 입니다.def code_name(data): result=pd.DataFrame(columns=['name','count','price']) df = pd.DataFrame(list(data['info'].str.split('/'))) # '/ ' 로 구분하여 문자열을 나누어 리스트에 넣음 result['name'] = df[0] # 첫번째 값인 이름이 입력 result['count']= df[1] # 두번째 값인 수량이 입력 result['price']= df[2] # 세번째 값인 가격이 입력 result = result.astype({'count':int,'price':int}) # count와 price를 int로 바꿈(기존str) return result print(code_name(org_data))
value_cal(data,unit=' ')은 가격과 수량을 곱한다음에 단위로 unit arg를 붙이는 함수입니다.
def value_cal(data,unit=''): result = pd.DataFrame(columns=['name','value']) result['name'] =data['name'] # 이름은 기존거를 가져옴 result['value']=data['count']*data['price'] # value는 count * price를 입력함 result = result.astype({'value':str}) # value를 str로 변경(단위를 붙이기 위함) result['value']=result['value']+unit # 단위를 붙임 return(result) input=code_name(org_data) print(value_cal(input,'원'))
pipe 메서드를 사용하지 않는경우
만약 pipe메서드를 사용하지 않는다면 아래와같이 함수를 사용해야 합니다.
(사용 예시1)print(value_cal(code_name(org_data),'원'))
pipe메서드를 사용한다면 아래와같이 직관적으로 나타낼 수 있다.
(사용 예시2)print(org_data.pipe(code_name).pipe(value_cal,'원'))
agg메서드는 apply와 비슷하게 함수를 적용하는 메서드이지만,
여러개의 함수를 동시에 적용할 수 있다는 장점이 있습니다.
그리고 name 를통해 사용자정의 함수명을 따로 설정할경우 그 이름을 사용한다는 점을 활용하여
함수를 사용한 DataFrame을 보다 깔끔하게 정리하는데도 용이하게 쓸 수 있습니다.
기본 사용법
df.agg(func=None, axis=0, args, kwargs)
func : 함수입니다.
axis :{0 : index(row) / 1 : columns} 축입니다 0은 행, 1은 열 입니다. arg : 함수의 인수 입니다..
kwargs : dict 형태의 함수의 인수입니다.
먼저 간단한 3x3짜리 데이터를 만들어보겠습니다.
df = pd.DataFrame([[1,4,7],[2,5,8],[3,6,9]]) print(df)
입력되는 함수의 형태에 따라
입력함수로는 먼저 np.함수 형태나 그냥 문자열 형태로의 입력이 가능합니다.
np함수의 경우ex1 = df.agg(np.prod) print(ex1)
문자열일 경우
ex2 = df.agg('prod') print(ex2)
lambda함수나 사용자 정의 함수를사용할 수도 있습니다.
lambda함수를 사용할 경우 열 명칭은 lambda가 됩니다.ex3 = df.agg([lambda x : min(x) * max(x)]) print(ex3)
사용자정의 함수를 사용하게되면 기본적으로 함수명 열 이름으로 설정이 됩니다.
def func_sub(input): return max(input)-min(input) ex4 = df.agg([func_sub,'sum']) print(ex4)
만약 함수명을 name 메서드를 통해 따로 설정해주면 그 이름이 쓰입니다.
def func_sub(input): return max(input)-min(input) func_sub.__name__='내함수' ex5 = df.agg([func_sub,'sum']) print(ex5)
여러 함수를 동시에 적용하는 경우
list나 dict형태로 func값을 입력하는 경우 여러 함수를 동시에 적용할 수 있습니다.
list로 입력하는 경우ex6 = df.agg(['min','max','sum','prod']) print(ex6)
dict를 이용하는 경우 순서를 변경하는것도 가능합니다.
ex7 = df.agg({2:'sum',0:'max',1:'min'}) print(ex7)
dict함수내에 다중함수를 적용할 수도 있습니다. 이 경우 해당되지 않는 index는 NaN을 출력합니다.
ex8 = df.agg({0:['sum','prod'],1:['max','min'],2:'mean'}) print(ex8)
axis인수를 변경할 경우
axis의경우 0이면index, 1이면columns기준으로 연산을 진행합니다.
(실행 결과1)ex2 = df.agg('prod', axis=0) print(ex2)
(실행 결과2)ex3 = df.agg('prod', axis=1) print(ex3)
transform메서드는 agg와 비슷하게 함수를 적용하는 메서드이지만,
단일 요소별로 함수를 동시에 적용할 수 있다는 장점이 있습니다. 마치 apply와 applymap의 차이와 비슷합니다.
기본 사용법
df.transform(func, axis=0, args, kwargs)
func : 함수입니다.
axis :{0 : index(row) / 1 : columns} 축입니다 0은 행, 1은 열 입니다.
arg : 함수의 인수 입니다.
kwargs : dict 형태의 함수의 인수입니다.
먼저 간단한 3x3짜리 데이터를 만들어보겠습니다.
col = ['col1','col2','col3']
row = ['row1','row2','row3']
df = pd.DataFrame(data=[[10,40,70],[20,50,80],[30,60,90]],index=row,columns=col)
print(df)

입력되는 함수의 형태에 따라
입력함수로는 먼저 np.함수 형태나 그냥 문자열 형태로의 입력이 가능합니다.
np함수의 경우ex1 = df.transform(np.sqrt) print(ex1)
문자열일 경우
ex2 = df.transform('sqrt') print(ex2)
lambda함수나 사용자 정의 함수를사용할 수도 있습니다.
agg와 다르게 기존 레이블이 표시됩니다.ex3 = df.transform(lambda x : np.sqrt(x)) print(ex3)
여러 함수를 동시에 적용하는 경우
list나 dict형태로 func값을 입력하는 경우 여러 함수를 동시에 적용할 수 있습니다.
list로 입력하는 경우 마치 multi index처럼 multi columns가 생성됩니다.ex4 = df.transform(['exp','sqrt']) print(ex4)
dict를 이용하는 경우 순서를 변경하는것도 가능합니다.
ex5 = df.transform({'col2':'exp','col1':'sqrt'}) print(ex5)
eval메서드는 파이썬의 eval 메서드와 사용목적이 동일합니다. 문자열로 된 계산식을 적용합니다.
기본 사용법
df.eval(expr, inplace=False, kwargs)
expr : 문자열 형태의 계산식입니다.
inplace : {True / False} 계산된 값이 원본을 변경할지의 여부입니다. 기본적으로 원본은 변경되지 않습니다.
먼저 기본적인 3x3 DataFrame을 만들어보겠습니다.
data = [[1,2,3],[4,5,6],[7,8,9]] col = ['col1','col2','col3'] row = ['row1','row2','row3'] df = pd.DataFrame(data = data, index = row, columns= col) print(df)
기본적인 사용법
col1*col2-col3의 값을 갖는 col4를 만들어보겠습니다. 'col4'='col1'+'col2'-'col3'를 문자열 그대로 사용합니다.
계산이 적용된 col4열이 생성된 것을 확인할 수 있습니다.print(df.eval('col4=col1*col2-col3'))
하지만 inplace인수가 기본값인 False이기 때문에 원본은 변경되지 않은것을 알 수 있습니다.
print(df)
inplace = True인 경우
Inplace = True로 할 경우 원본이 변경되는것을 확인할 수 있습니다.
inplace = True로 할경우 사본이 생성되지 않기 때문에 print할 경우 None이 출력됩니다.print(df.eval('col4=col1*col2-col3',inplace=True))
하지만 원본은 변경되어있는것을 확인할 수 있습니다.
print(df)