적용할 함수, 대상에 따른 차이
pandas의 객체(pandas.DataFrame, pans.Sries)에 함수를 적용할 경우, 어떠한 함수에 적용하는가 그리고 요소/행/열 어디에 적용할 것인가에 따라 사용하는 메소드가 달라진다.
- Numpy함수의 인수로 pandas객체를 지정
- 함수의 인수에 pandas객체를 지정하는 것이 가능하다.
- 함수의 종류 및 인수의 설정에 따라 요소/행/열에 적용되는 방법이 다르다
- pandas객체의 메소드로 사전에 정의되어 있는 함수도 있다.
- pandas객체의 메소드에 함수를 적용
- 요소(스칼라값)에 관한 함수
+ Series의 각 요소에 적용: map(), apply()
+ DataFrame의 각 요소에 적용: applymap()
- 행/열(1차원 배열)에 관한 함수
+ DataFrame의 각 행/ 각 열에 적용 : apply()
+ DataFrame의 특정 행/특정 열에 적용
이번 포스팅에서는 아래와 같은 csv파일이 존재하고 있다고 가정하고 설명하도록 하겠다.
a,b,c,d
11,12,13,14
21,22,23,24
31,32,33,34
csv 파일은 다음과 같이 Pandas의 pd.read_csv('파일경로')로 읽어들일 수 있다.
import pandas as pd
import numpy as np
df = pd.read_csv('data/src/sample_header.csv')
print(df)
# a b c d
# 0 11 12 13 14
# 1 21 22 23 24
# 2 31 32 33 34
Numpy함수의 인수로 pandas객체를 지정
Numpy함수의 인수로 pandas를 지정할 수 있다.
요소로 적용
Numpy의 유니버셜 함수(ufumc: 배열의 요소로 적용되는 함수)는 pandas객체의 각 요소에 적용될 수 있다.
Numpy의 유니버셜 함수로는 다양한 함수가 있지만 예를 들면 절대값(fabs())이나 제곱근(sqrt()), log(log())등이 있다.
print(np.sqrt(df))
# a b c d
# 0 3.316625 3.464102 3.605551 3.741657
# 1 4.582576 4.690416 4.795832 4.898979
# 2 5.567764 5.656854 5.744563 5.830952
행/열에 적용
Numpy배열의 모든 요소의 값을 계산하는 함수의 인수로 pandas객체를 지정하면, 기본적으로 pandas객체의 각 열에 대해 적용된다. 인수 axis=1로 지정하면, 각 행에 대해서 적용된다.
최대 (amax()) 나 최소(amin()), 평균(mean())등 을 구할 때 유용하게 사용할 수 있다.
print(np.amax(df))
# a 31
# b 32
# c 33
# d 34
# dtype: int64
print(np.mean(df, axis=1))
# 0 12.5
# 1 22.5
# 2 32.5
# dtype: float64
(추가) pandas.DataFrame, pandas.Series 의 메소드
최대, 최소, 평균, 분산 등은 pandas 객체의 메소드로써도 준비되어 있어 있다(물론 다른 함수들도 있다). 이 경우에도 기본적으로 각 열에 적용되며, axis=1로 지정하면 각 행에 적용된다.
print(df.max())
# a 31
# b 32
# c 33
# d 34
# dtype: int64
print(df.max(axis=1))
# 0 14
# 1 24
# 2 34
# dtype: int64
pandas객체의 메소드로 함수를 적용
pandas객체의 메소드를 사용하여 요소나 행/열에 함수를 적용하는 것이 가능하다. python의 내장 함수, 유저가 정의한 함수 상관없이 적용할 수 있다. 물론 Numpy의 함수도 가능하다.
- Series의 각 요소에 적용 : map(), apply()
- DataFrame의 각 요소에 적용: applymap()
- DataFrame의 각 행/각 열에 적용: apply()
어떠한 메소드도 처리된 새로운 pandas객체를 리턴하고, 원래의 객체는 바뀌지 않는다. dropna()나 fillna()과 같이 인수 inplace는 없기 때문에, 원래의 객체 자체도 바꾸고 싶은 경우는 다음과 같이 할 수 있다.
df = df.applymap(function)
즉, 새로운 객체를 원래의 객체에 대입하면 간단히 해결된다.
Series의 각 요소에 적용 : map(), apply()
python의 내장함수, 무명 함수(lambda)나 def로 정의한 함수를 map()혹은 apply()인수로 전달한다.
s = df['a']
print(s)
# 0 11
# 1 21
# 2 31
# Name: a, dtype: int64
f_brackets = lambda x: '[{}]'.format(x)
print(s.map(f_brackets))
# 0 [11]
# 1 [21]
# 2 [31]
# Name: a, dtype: object
def f_str(x):
return str(x).replace('1', 'One').replace('2', 'Two').replace('3', 'Three').replace('4', 'Four')
print(s.map(f_str))
# 0 OneOne
# 1 TwoOne
# 2 ThreeOne
# Name: a, dtype: object
map()의 경우, 인수에 사전형dict를 지정하면 요소 치환이 된다. 또한 문자열에 대한 치환 등의 처리는 정의되어 있는 문자열 메소드를 이용한 방법을 통해 이루어진다. 향후에 시간이 된다면 이 부분에 대한 포스팅을 하도록 하겠다.
DataFrame의 각 요소에 적용: applymap()
위와 동일하게 Python의 내장 함수, 무명함수(lambda)나 def로 정의된 함수를 applymap()의 인수로 전달한다.
f_oddeven = lambda x: 'odd' if x % 2 == 1 else 'even'
print(df.applymap(f_oddeven))
# a b c d
# 0 odd even odd even
# 1 odd even odd even
# 2 odd even odd even
DataFrame의 각 행/각 열에 적용: apply()
1차원 배열에 적용 가능한 함수를 apply()의 인수로 전달한다. 디폴트로는 각 행에 대해 적용되며, 열에 적용하기 위해서는 axis=1를 지정해줘야한다.
f_maxmin = lambda x: max(x) - min(x)
print(df.apply(f_maxmin))
# a 20
# b 20
# c 20
# d 20
# dtype: int64
print(df.apply(f_maxmin, axis=1))
# 0 3
# 1 3
# 2 3
# dtype: int64
DataFrame의 특정 행/특정 열에 적용
DataFrame의 특정 행/특정 열에[만 함수를 적용하는 별도의 함수는 없기 때문에,
1) 행 / 열을 선택하고, Series로 map() 또는 apply()에 적용한다
2) 원래의 행/열에 대입하여 덮어쓴다
위와 같은 순서로 처리한다.
df['b'] = df['b'].map(f_str)
print(df)
# a b c d
# 0 11 OneTwo 13 14
# 1 21 TwoTwo 23 24
# 2 31 ThreeTwo 33 34
df.iloc[2] = df.iloc[2].map(f_str)
print(df)
# a b c d
# 0 11 OneTwo 13 14
# 1 21 TwoTwo 23 24
# 2 ThreeOne ThreeTwo ThreeThree ThreeFour
참고자료
'IT > 언어' 카테고리의 다른 글
[python] 다중상속 (0) | 2021.05.28 |
---|---|
[python] python으로 JSON 파일 다루는 기초적인 방법 (0) | 2021.05.22 |
[python] pathlib 사용법 (패스(경로)를 객체로써 조작, 처리) (0) | 2021.05.15 |
[python] python의 self와 __init__의 이해 (6) | 2021.05.14 |
[python] Python 정규표현 모듈 re 사용법 (match, search, sub등) (0) | 2021.05.12 |