아는 만큼 보인다

[Pandas/Python] Pandas로 데이터 전처리할 때 method chaining (함수 연속적용) 직관적으로 하기 본문

Pandas

[Pandas/Python] Pandas로 데이터 전처리할 때 method chaining (함수 연속적용) 직관적으로 하기

계토 2022. 9. 19. 14:17

데이터 전처리를 하다보면, 여러 개의 함수를 연속적으로 사용해야 할 때가 있다. 데이터와 분석 목적에 따라 전처리 과정은 몹시 길 수도 있는데, 이것을 잘 정리해주지 않으면 오류가 발생하기 쉽고 비효율적인 코드가 되거나, 미래의 나와 팀원이 이해하기 어려운 코드가 될 수 있다. 이번 글에서는 method chaining을 통해 좀 더 간결하고 직관적으로 데이터 전처리 코드를 짜는 방법에 대해 알아보고자 한다.

 

예시와 함께 보도록 하자! 예시는 Iris dataset과 함께 살펴보도록 하겠다.

 

Iris dataset의 table 구조는 다음과 같다.

data = pd.read_csv('Iris.csv')
data
  Id SepalLengthCm SepalWidthCm PetalLengthCm PetalWidthCm Species
0 1 5.1 3.5 1.4 0.2 Iris-setosa
1 2 4.9 3.0 1.4 0.2 Iris-setosa
2 3 4.7 3.2 1.3 0.2 Iris-setosa
3 4 4.6 3.1 1.5 0.2 Iris-setosa
4 5 5.0 3.6 1.4 0.2 Iris-setosa
... ... ... ... ... ... ...

 

여기서, SepalLengthCm 기준 4.5 이상인 것들만 필터링한 후, 각 Species마다 데이터가 몇 개씩 있는지 count하고 싶다고 가정하자.

 

따로 method chaining을 사용하지 않는 경우, 코드는 다음과 같다.

# filter based on SepalLengthCm > 4.5
data = data[data['SepalLengthCm'] > 4.5]

# count data after grouping by "Species"
data = data.groupby("Species").count()

# Select "Id" column
data = data[["Id"]]

data
  Id
Species  
Iris-setosa 45
Iris-versicolor 50
Iris-virginica 50

SepalLengthCm으로 필터링 한 후, Species로 grouping하여 count()를 사용하여 데이터 개수를 확인했다.
마지막으로, Id column만 가져와 간단하게 결과를 확인했다.

 

어떤 것을 하려는지 잘 보이긴 하지만 코드가 너무 길고! 같은 변수명을 사용해서 코드 작성 과정에서 error prone할 수 있다.
(물론 변수명을 바꿔서(data1, data2, etc.) 약간의 문제를 해결할 수는 있으나, 그 경우 적용하려는 함수 개수에 따라 local variable의 수가 늘어나 복잡한 코드가 탄생할 수 있다)

 

이걸 조금 더 간단하게 할 수 있는데, 방법은 아래와 같다.

data = data[data['SepalLengthCm'] > 4.5].groupby("Species").count()[["Id"]]
data
  Id
Species  
Iris-setosa 45
Iris-versicolor 50
Iris-virginica 50

그냥 모든 함수를 다 이어주었다!

물론 지금은 적용하려는 함수가 많지 않아, 이렇게 되어 있어도 하려는 일이 무엇인지 충분히 알 수 있다.

 

그러나 column의 이름이 길거나 적용하려는 함수가 많아질 수록 코드는 끝도 없이 길어지고, 다른 사람이 보기에 직관적이지 않은 코드가 된다.

 

그럼 여기서 어떻게 더 개선할 수 있을까?

코드 양옆에 ()를 넣어주고 함수별로 정리해주는 방법이 있다.

data = (
    data
    [data['SepalLengthCm'] > 4.5]
    .groupby("Species")
    .count()
    [["Id"]]
)
data
  Id
Species  
Iris-setosa 45
Iris-versicolor 50
Iris-virginica 50

즉 단순히 코드를 ()에 넣고, 실행하려는 각 함수별로 줄바꿈을 해주면 된다.

 

이렇게 해주면,

내가 나중에 다시 꺼내어 보아도 무엇을 하고 있는지 이해할 수 있고, 다른 사람이 보아도 차근차근 따라가기 쉬운 코드를 만들 수 있다!

또한 여러 의미 없는 변수를 따로 정의해주지 않아도 되고, 이후에 코드를 수정할 때에도 좀 더 빨리 할 수 있기도 하다!

 

참고로, 나는 기존에 R 유저였어서 %>%를 사용해서 method chaining을 많이 했었는데 이번에 입사하며 pandas로는 그렇게 할 수 없을까 생각하게 되어 찾아보던 중 발견한 방법이다.

 

참고자료: https://towardsdatascience.com/the-flawless-pipes-of-python-pandas-30f3ee4dffc2