10-2 apply 메서드 활용하기 - 기초
다음 실습을 통해 apply 메서드 활용법을 알아보겠다. apply 메서드로 브로드캐스팅한 결과가 올바른 값인지 확인하기 위해 시리즈, 데이터프레임의 기초 연산 결과와 비교하며 실습을 진행하겠다.
In [27]:
# 데이터 프레임 준비
import pandas as pd
df = pd.DataFrame({'a':[10, 20, 30], 'b':[20, 30, 40]})
print(df)
a b 0 10 20 1 20 30 2 30 40
In [28]:
# 제곱 함수 준비
def my_sq(x):
return x ** 2
In [30]:
# n제곱 함수 준비
def my_exp(x, n):
return x ** n
다음은 앞에서 만든 제곱 함수(my_exp)를 사용하기전에 a 열을 제곱하여 얻은 결과이다. 이 결괏값과 apply 메서드를 적용한 결괏값을 비교해 보겠다.¶
In [32]:
print(df['a'] ** 2)
0 100 1 400 2 900 Name: a, dtype: int64
다음은 apply 메서드에 제곱 함수의 이름(my_sq)을 전달하여 시리즈의 모든 데이터에 제곱 함수를 적용한 것이다. 이때 apply 메서드에 전달하는 함수(my_sq)가 1개 인자를 받도록 구성되어 있다면 인잣값을 생략해야 한다. 그러면 2개의 인자를 전달해야 할 경우에는 어떻게 해야 할까?¶
In [34]:
sq = df['a'].apply(my_sq)
print(sq)
0 100 1 400 2 900 Name: a, dtype: int64
이제 4개의 인자를 전달받아야 하는 n 제곱 함수(my_exp)와 apply 메서드를 함께 사용해 보겠다. apply 메서드의 첫 번째 인자에는 n 제곱 함수의 이름(my_exp)을 전달하고 두 번째 인자에는 n 제곱 함수의 두 번째 인자(n)을 전달한다.¶
In [35]:
ex = df['a'].apply(my_exp, n=2)
print(ex)
0 100 1 400 2 900 Name: a, dtype: int64
In [36]:
ex = df['a'].apply(my_exp, n=3)
print(ex)
0 1000 1 8000 2 27000 Name: a, dtype: int64
데이터프레임과 apply 메서드¶
이번에는 시리즈가 아니라 데이터프레임에 apply 메서드를 사용하는 방법을 알아보자. 먼저 데이터프레임을 다음과 같이 준비한다.
In [37]:
df = pd.DataFrame({'a':[10, 20, 30], 'b':[20, 30, 40]})
print(df)
a b 0 10 20 1 20 30 2 30 40
새로운 함수를 만들어보겠다. 이번에 사용할 함수는 1개의 값을 전달받아 출력하는 함수이다.¶
In [38]:
def print_me(x):
print(x)
이번에는 데이터프레임에 함수를 적용해야 하기 때문에 함수를 열 방향으로 적용할지 행 방향으로 적용할지 정해야 한다. axis 인잣값을 0이나 1로 지정하면 함수를 열 또는 행 방향으로 적용할 수 있다.¶
In [43]:
print(df.apply(print_me, axis=0))
0 10 1 20 2 30 Name: a, dtype: int64 0 20 1 30 2 40 Name: b, dtype: int64 a None b None dtype: object
In [44]:
print(df['a'])
0 10 1 20 2 30 Name: a, dtype: int64
In [45]:
print(df['b'])
0 20 1 30 2 40 Name: b, dtype: int64
이번에는 3개의 인자를 입력받아 평균을 계산하는 함수를 사용해 보겠다.¶
In [46]:
def avg_3(x, y, z):
return (x + y + z) / 3
그런데 avg_3 함수를 apply 메서드에 전달하면 'avg_3 함수는 3개의 인잣값을 필요로 하는 함수인데 1개의 인잣값만 입력받았다'는 오류 메시지가 출력된다. 즉, avg_3 함수에 열 단위 데이터(df['a'] 또는 df['b']가 전달되었고 이 값을 avg_3 함수에서 1개의 인자로 인식한 것이다. 따라서 avg_3 함수가 열 단위로 데이터를 처리할 수 있도록 수정해야 한다.¶
In [47]:
print(df.apply(avg_3))
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) /tmp/ipykernel_7534/1813414437.py in <module> ----> 1 print(df.apply(avg_3)) ~/anaconda3/lib/python3.9/site-packages/pandas/core/frame.py in apply(self, func, axis, raw, result_type, args, **kwargs) 8846 kwargs=kwargs, 8847 ) -> 8848 return op.apply().__finalize__(self, method="apply") 8849 8850 def applymap( ~/anaconda3/lib/python3.9/site-packages/pandas/core/apply.py in apply(self) 731 return self.apply_raw() 732 --> 733 return self.apply_standard() 734 735 def agg(self): ~/anaconda3/lib/python3.9/site-packages/pandas/core/apply.py in apply_standard(self) 855 856 def apply_standard(self): --> 857 results, res_index = self.apply_series_generator() 858 859 # wrap results ~/anaconda3/lib/python3.9/site-packages/pandas/core/apply.py in apply_series_generator(self) 871 for i, v in enumerate(series_gen): 872 # ignore SettingWithCopy here in case the user mutates --> 873 results[i] = self.f(v) 874 if isinstance(results[i], ABCSeries): 875 # If we have a view on v, we need to make a copy because TypeError: avg_3() missing 2 required positional arguments: 'y' and 'z'
다음은 avg_3 함수가 열 단위로 데이터를 처리할 수 있도록 개선한 avg_3_apply 함수이다. 개선한 함수를 apply 메서드에 적용하면 잘 동작하는 것을 알 수 있다.¶
In [58]:
def avg_3_apply(col):
x = col[0]
y = col[1]
z = col[2]
return (x + y + z) / 3
print(df.apply(avg_3_apply))
a 20.0 b 30.0 dtype: float64
앞의 과정에서는 데이터프레임의 행 개수가 3개라는 것을 알고 있다는 전제하에 avg_3_apply 함수를 작성했다. 하지만 일반적으로는 for문을 이용하여 다음과 같이 작성한다.¶
In [59]:
def avg_3_apply(col):
sum = 0
for item in col:
sum += item
return sum / df.shape[0]
과정 11의 함수를 응용하면 행 방향으로 데이터를 처리하는 함수도 만들 수 있다. 마지막 return문의 df.shape[0]을 df.shape[1]로 바꾸면 된다.¶
In [60]:
def avg_2_apply(col):
sum = 0
for item in col:
sum += item
return sum / df.shape[1]
print(df.apply(avg_2_apply, axis=1))
0 15.0 1 25.0 2 35.0 dtype: float64
출처 : Do it! 데이터 분석을 위한 판다스
'Python > Pandas' 카테고리의 다른 글
<파이썬 판다스> Chapter 11-1 데이터 집계 (0) | 2023.05.17 |
---|---|
<파이썬 판다스> Chapter 10-3 apply 메서드 활용하기 - 고급 (0) | 2023.05.14 |
<파이썬 판다스> Chapter 10-1 간단한 함수 만들기 (0) | 2023.05.14 |
<파이썬 판다스> Chapter 09-4 정규식으로 문자열 처리에 날개 달기 (0) | 2023.05.14 |
<파이썬 판다스> Chapter 09-3 문자열 포매팅 (0) | 2023.05.09 |