• 카테고리

    질문 & 답변
  • 세부 분야

    데이터 분석

  • 해결 여부

    해결됨

pandas beginner #2 질문 있습니다!

22.05.20 22:59 작성 조회수 135

0

안녕하세요!

데이터 프레임에서 열을 불러오는 코드가 조금 헷갈려서 질문드립니다!

예제 3번에서

df['median_house_value'][df['period_grade'] == 'bad'].mean() 와

df[df['period_grade'] == "bad"]['median_house_value'].mean() 사이의 차이가 무엇일까요?

 

혹 둘 중 더 좋은 코드가 있다면 더 좋은 이유 역시 궁금합니다!

답변 1

답변을 작성해보세요.

1

DQ K님의 프로필

DQ K

지식공유자

2022.05.21

안녕하세요, 정연님.

답변드립니다.

 

# 1. 두 코드의 차이

- 슬라이싱에는 크게 두 가지 방식이 있습니다.

- 하나는 특정 열을 가져오는 것, 다른 하나는 특정 행을 가져오는 것입니다.

- 각 행이나 열의 이름이나 index를 통해 바로 가져오는 방법이 있고,

- 조건문을 통해 True에 해당하는 행이나 열만을 가져오는 방법이 있습니다.

- 이러한 두 방법을 동시에 사용하거나 중복적으로 사용하는 것도 가능합니다.

 

- 위 두 코드의 경우, 하나는 열의 이름을 통해 불러온 상태에서 행의 조건문을 통해 조회하는 것과

   행의 조건문을 조회한 후 열의 이름을 불러오는 것의 차이이며 결과적인 차이는 없습니다.

- 이후 배우게 될 조건문에는 하나의 대괄호 안에 여러 조건문을 사용하거나, iloc, loc 안에 조건문을 포함시키는 등의 다소 복잡할 수 있는 스킬을 배우시게 될텐데요. 그때에도 지금 하시는 것처럼 여러 조건을 하나의 대괄호에 여러 개의 조건을 적는 것보다 나눠서 적는 것이 편할 수 있습니다.

- 글로만 이해하는 것은 어려우니 코드로 확인해볼까요?

 

-- 우선 아래와 같이 데이터를 불러와보겠습니다.

-- 조회 성능을 확인하기 위해 데이터 규모를 좀 늘려서 진행합니다.

import pandas as pd
from tqdm import tqdm

def modifier(x:
  return str(int(x) // 10 * 10) + "+ years"

df = pd.read_csv('/content/sample_data/california_housing_train.csv')
df['housing_period'] = df['housing_median_age'].apply(modifier)
df['period_grade'] = df['housing_period'].map(lambda x : "good" if int(x[:-7]) < 20 else ("normal" if int(x[:-7]) < 40 else "bad"))
 
for _ in tqdm(range(5)) :
  df = pd.concat([df, df], ignore_index=True)
df.info()
df

-- 이후 중복 조건문을 통해 housing_median_age가 10과 30 사이에 있는 'total_bedrooms' 칼럼만을 조회해보도록 하겠습니다.

df1 = df[(df.housing_median_age > 10) & (df.housing_median_age < 30)]['total_bedrooms']
df1

위 코드의 결과와 아래 코드의 결과는 완전히 동일합니다.

df1 = df['total_bedrooms'][(df.housing_median_age > 10) & (df.housing_median_age < 30)]
df1

 

-- colab이나 jupyter notebook 과 같은 작업 환경에서 지원되는 magic function 중 하나인 %%timeit을 이용해 작동 시간을 동시에 체크해보겠습니다.

1) 행 조건문 적용 후 열 조회

%%timeit -n 5 -r 5
df1 = df[(df.housing_median_age > 10) & (df.housing_median_age < 30)]['total_bedrooms']
df1

2) 열 적용 후 행 조건문 조회

%%timeit -n 5 -r 5
df1 = df['total_bedrooms'][(df.housing_median_age > 10) & (df.housing_median_age < 30)]
df1

아래의 방법이 더 빠른 결과를 내게 됩니다!

사실 파이썬의 판다스 데이터 프레임의 경우, 행열을 조회하는 과정에서

많은 부분을 캐시화해 사용하기에 두 기능의 차이는 크지 않습니다.

(오히려 일정 이상 데이터 사이즈가 커지면 우열 관계가 없어지거나 역전되기도 합니다)

이러한 이유로 저 두 방법의 성능차이를 굳이 고려하실 필요는 없지만,

추후 Time Series Data와 같이 어마어마한 양의 데이터를 다루게 되신다면 그때는 위와 같이 Column 중심의 데이터 우선 선택이 중요해질 수 있습니다.

 

-- 마지막으로 위에서 언급한 바와 같이 괄호와 &를 이용해 하나의 대괄호 안에 여러 개의 조건문을 사용했을 때와 사용하지 않았을 때를 비교해보고 마치겠습니다.

1) 행 조건문을 통해 선조회 후 해당 칼럼 조회

%%timeit -n 5 -r 5
df2 = df[(df.housing_median_age > 10)][(df.housing_median_age < 30)]['total_bedrooms']
df2

2) 열 조회 후 열 조건으로 조회

%%timeit -n 5 -r 5
df2 = df['total_bedrooms'][(df.housing_median_age > 10)][(df.housing_median_age < 30)]
df2

오히려 이 경우엔 하나의 대괄호 안에 중복으로 적용한 것보다 유의미한 속도차이가 나게 됩니다.

 

[ 정 리 ]

1. 판다스 데이터 프레임의 슬라이싱 및 조회의 순서 차이에 대한 성능 차이는 거의 없다. 있어도 유의미하지 않으며, 절대적이지도 않다.

2. 여러 조건문을 적용할 때에는 여러 개로 나눠쓰는 것과 한 번에 쓰는 것의 결과물 차이는 없지만, 성능 차이는 나게 된다.

3. 다만 위의 두 경우 모두 빅분기 시험 목적으로는 고려하지 않아도 충분하며, 현업 단계에서는 spark를 통한 대규모 데이터 처리, streaming 데이터와 같은 상황이라면 고려해볼만 하다.

 

위에서 사용한 코드가 저장된 COLAB notebook을 공유드립니다.

아래 바로가기를 클릭해서 본인의 드라이브로 복사본을 만든 뒤 몇 번 해보시면 금방 익숙해지실 겁니다~

바로가기

 

정연님뿐 아니라 다른 수강생분들에게도 도움될 수 있는 질문 감사드리며,

이해안되는 게 있거나 추가로 궁금한게 생기면 언제든 질문주시면 감사하겠습니다.