파이썬 판다스 데이터프레임 함수 적용 : pd.transform()
안녕하세요. 지난 번에 다뤘던 apply 함수에 이어, 이번에는 판다스 데이터프레임의
각 행, 열에 함수를 적용할 수 있는 좀더 간단한 방법인 transform 함수의 예제를
살펴보도록 하겠습니다.
궁금하신 분들을 위하여
지난 번에 다룬 apply 함수 사용법에 대한 글의 링크는 아래에 첨부해두겠습니다.
두 함수의 세부적인 용도나 결과 형태의 차이는 여기서는 깊게 다루지는 않고,
이 차이에 대한 내용은 추후에 기회가 된다면 따로 다루겠으며,
여기서는 transform 함수의 예제에 집중하여 글을 작성해보도록 하겠습니다.
참고로, 이 글은 판다스 transform 함수의 공식 문서 내용에 기반하여 작성되었습니다.
pd.transform 함수 기본 예제(모든 열에 적용)
우선, 다음과 같은 간단한 데이터프레임이 있다고 가정해보겠습니다.
import pandas as pd
df = pd.DataFrame({'col1' : [1, 3, 5], 'col2' : [2, 4, 6], 'col3' : ['a', 'b', 'c']})
print(df)
# 결과
col1 col2 col3
0 1 2 a
1 3 4 b
2 5 6 c
세 개의 열을 가지고 있으며,
col1, col2는 숫자형, col3은 문자열 자료형으로 이루어진 데이터프레임입니다.
이제 이 열에 간단하게 lambda로 구현된 곱셈 연산을 수행해보겠습니다.
참고로, 곱셈 연산은 숫자형, 문자열 자료형 모두에서 지원하는 점에 참고해주세요.
print(df.transform(lambda x : x * 2))
# 결과
col1 col2 col3
0 2 4 aa
1 6 8 bb
2 10 12 cc
col1, col2 열은 숫자 값이 2배가 되었고, col3 열은 문자가 두 글자씩으로 늘어났습니다.
만일, 일부 column에서만 지원하는 연산 형태를 넣으면 오류가 발생할 수 있습니다.
print(df.transform(lambda x : x + 2))
# 결과
TypeError: can only concatenate str (not "int") to str
문자열 자료형에는 + 2 라는 숫자 덧셈은 허용하지 않아 TypeError가 발생했습니다.
다만, 이런 경우 뒤에서 설명할 리스트에 함수 목록을 넣는 방법을 사용하면
연산이 가능한 column에만 적용할 수 있습니다.
참고로 def 형태로 작성된 함수의 경우도 적용하는 데에는 문제가 없습니다.
def mul_2(x):
return x * 2
print(df.transform(mul_2))
# 결과
col1 col2 col3
0 2 4 aa
1 6 8 bb
2 10 12 cc
pd.transform 여러 함수 동시 적용
만일 리스트에 여러 함수의 목록을 묶어서 넣어준다면,
각 column마다 각 연산을 실행한 결과들을 일일히 출력해줍니다.
다만, 특정 column에는 연산이 불가능한 경우는 이 방법을 적용하면
필터링하여 가능한 column들에만 결과를 적용해서 보여줄 수 있습니다.
만일 2를 더하는 add_2, 'k'를 뒤에 붙이는 add_k, 그리고 넘파이에서 제공하는
exp 함수 총 3가지를 동시에 적용하면 어떻게 될까요? 아래 예시를 살펴보겠습니다.
숫자형 자료형에 가능한 연산은 add_2와 exp연산이고,
문자열 자료형에 가능한 연산은 add_k이기에
각 column에 가능한 연산의 조합들이 수행된 결과를 살펴볼 수 있었습니다.
transform과 groupby 연계 사용
groupby 함수와 연계하여 사용할 경우, 각 행에 groupby 함수의 결과를 가져와
적용하는 코드가 매우 간단해집니다. 이에 대한 의미를 이해해보기 위하여
다음 예시 데이터프레임을 살펴보겠습니다.
df = pd.DataFrame({'name' : ['a', 'a', 'b', 'b'], 'score' : [10, 15, 8, 6]})
# 데이터프레임 상태
name score
0 a 10
1 a 15
2 b 8
3 b 6
df.groupby('name')['score'].mean()
# 그룹화 결과
name
a 12.5
b 7.0
만일 name을 기준으로 각 name의 score 평균을 구해보면 위와 같이 계산이 됩니다.
이제 그룹화 결과에 .mean()이 아니라 transform을 적용해보겠습니다.
df.groupby('name')['score'].transform(np.mean)
# transform 결과
0 12.5
1 12.5
2 7.0
3 7.0
원래 데이터프레임의 각 row의 name에 해당하는 평균 점수가 반영되어
4개의 행이 모두 출력된 것을 확인할 수 있었습니다.
transform 함수 axis 설정 및 인덱스, 열 이름 활용
마지막으로 조금 복잡한 예시인 인덱스, 열 이름을 활용한 예제를 살펴보겠습니다.
transform 함수에는 axis 인자를 설정 가능한데, 0으로 설정하면 인덱스를 기준으로,
1로 설정하면 열 이름을 기준으로 데이터들을 가져올 수 있습니다.
먼저, 가장 앞의 예제에서 사용했던 데이터프레임을 다시 가져와
0번과 1번 인덱스의 값을 더하여 살펴보겠습니다.
인덱스를 기준으로 값을 가져와야 하기에 axis = 0으로 설정했습니다.
df = pd.DataFrame({'col1' : [1, 3, 5], 'col2' : [2, 4, 6], 'col3' : ['a', 'b', 'c']})
df.transform(lambda x : x[0] + x[1], axis = 0)
# 결과
col1 4
col2 6
col3 ab
col1에서는 가장 앞 데이터 두개인 1과 3이,
col2에서는 2와 4가, col3에서는 'a'와 'b'가 더해진 결과가
각각 열들을 기준으로 반환된 것을 확인해볼 수 있었습니다.
이번에는 col3의 값과 col1의 값을 각 행마다 불러와서
col3의 값을 col1의 수만큼 반복하여 출력하는 상황을 생각해보겠습니다.
여기서는 열 이름을 기준으로 값을 불러와야해서 axis = 1로 설정했습니다.
df = pd.DataFrame({'col1' : [1, 3, 5], 'col2' : [2, 4, 6], 'col3' : ['a', 'b', 'c']})
df.transform(lambda x : x['col3'] * x['col1'], axis = 1)
# 결과
0 a
1 bbb
2 ccccc
각 행의 col3 열 데이터인 'a', 'b', 'c'를 col1 열 데이터인 1, 3, 5회 만큼씩
반복하여 출력된 결과를 반환했습니다.
참고로 이 기능은 apply 함수에서도 동일하게 적용이 가능한 방법이며,
def를 이용한 함수 등에서는 아주 복잡한 기능도 구현이 가능하니
잘 활용하시면 매우 유용할 것으로 생각됩니다.
'Python > Pandas' 카테고리의 다른 글
[Pandas] 파이썬 데이터프레임 병합/합치기 함수 비교(merge, concat) (0) | 2021.12.30 |
---|---|
[Pandas] 데이터프레임 정렬하기 : sort_values, sort_index 함수 (0) | 2021.12.23 |
[Pandas] 파이썬 엑셀 파일 다루기 : read_excel, to_excel (0) | 2021.12.22 |