🚦 Summary

  • 판다스에서 쓰이는 axis 옵션은 데이터프레임에 대해 연산이 적용되는 방향에 대한 옵션입니다.
  • 하지만 실제로 코드가 작동할때는 연산이 적용되는 ‘대상’ 을 중점적으로 생각하는게 코드를 사용하는 것에 더 도움이 됩니다.
  • 처음 이 개념을 배우게 되면 연산의 방향과 대상을 혼동해 개념의 적용에 애를 먹거나, 일반적 상식으로 알고 있던 x축과 y축에 대한 개념으로 인해 사용법을 헷갈리기도 합니다.
  • 판다스에서 axis의 값이 0일때와 1일때 어떤 의미인지, 어떤 값을 기준으로 판단해야 하는지, 예제 코드 및 이미지 설명과 함께 살펴 봅니다.

 

📌 Intro.

  • 최근 머신러닝에 대해 학습하기에 앞서 Pandas에 대해 다시 뜯어보기를 하고 있습니다.

  • 머신러닝을 위한 데이터 전처리에 있어 pandas만큼 자주사용하는 도구가 없는데 막상 ‘정확하게 정의를 알고 있었나?’ 를 고민해보면 자신있게 말하기가 어렵습니다.

  • 이번에는 판다스를 쓰면서 가장 흔하게 헷갈리는 부분인 axis의 연산 방향에 대해 정리해 보겠습니다.


왜 헷갈리는지를 먼저 알아야 합니다.

✔️ 방향성의 반대개념

1️⃣ 행 방향(axis = 0)

  • 일반적 이해: 일반적으로 ‘행 방향’이라고 하면, 사람들은 데이터프레임에서 행이 수직방향으로 이어지는 것, 즉 세로 방향으로 생각합니다.

  • 판다스에서의 이해: 판다스에서 axis=0은 행 방향(세로)에 대한 '연산'을 의미합니다. 하지만 여기서 ‘행 방향(세로)에 대한 연산’은 각 열(column)을 따라 연산을 수행한다는 것을 의미합니다.

    즉, 하나의 열에 대해 연산을 적용한 후, 다음 열로 이동해 연산을 진행**하며, 이 방식으로 **데이터프레임 전체에 대해 연산을 수행합니다.

2️⃣ 열 방향(axis = 1)

  • 일반적 이해: ‘열 방향’이라고 하면, 데이터프레임에서 열이 수평방향으로 이어지는 것, 즉 가로 방향으로 생각하는 것이 일반적입니다.

  • 판다스에서의 이해: 판다스에서 axis=1은 열 방향(가로)에 대한 연산**을 의미합니다. 여기서 **‘가로에 대한 연산’은 각 행(row)을 따라 연산을 수행한다는 것을 의미합니다.

    즉, 하나의 행에 대해 연산을 적용한 후, 다음 행으로 이동해 연산을 진행**하며, 이 방식으로 **데이터프레임 전체에 대해 연산을 수행합니다.

✔️ 연산의 방향과 대상의 혼동

  • 판다스에서 axis에 대해 가장 혼동을 하는 주된 이유라 생각합니다.

  • 연산의 ‘방향’ 과 연산이 적용되는 '대상' 을 혼동하는 경우가 많습니다.(적어도 저는 그랬습니다 😂)

    • axis = 0행방향 연산이라는 의미이지만, 이것은 연산의 방향을 의미하며, 연산의 대상각 컬럼이 가진 모든 값(=모든 행) 입니다.
    • axis = 1열방향 연산이라는 의미이지만, 이것은 연산의 방향을 의미하며, 연산의 대상각 행이 가진 모든 컬럼(열)별 값 입니다.

✔️ 수학적 차원과의 혼동

  • 다른 프로그래밍언어를 배운분들이나 수학에 익숙하신분들이 종종 이 부분을 헷갈려하기도 합니다.

  • 기본적으로 기타 프로그래밍언어 또는 수학에서 ‘0축’ 과 ‘1축’ 은 보통 x축(가로=열)과 y축(세로=행)을 의미합니다.

  • 하지만 하지만 위에 정의한 것처럼 판다스에서의 ‘0축(0 axis)’는 ‘행의 방향’을 의미하며, ‘1축(1 axis)’는 ‘열의 방향’ 을 나타냅니다.

  • 그리고 이 0축의 연산이 적용되는 방향은 각 열(column)을 따르는 가로방향(수평)에 대한 독립적 연산이며, 1축의 연산이 적용되는 방향은 각 행(row)를 따르는 세로방향(수직)에 대한 연산을 의미합니다.

  • 이러한 이유로 기존에 알고 있던 개념과의 차이로 인해 혼동이 발생할 수 있습니다.


  • 아직까지는 다소 헷갈릴 수 있습니다.따라서 실제 판다스에서 axis의 옵션(0 또는 1)에 따라 어떻게 연산이 일어나는지 예제 코드와 함께 살펴보도록 하겠습니다.
  • 일반적인 판다스의 함수에서 각 axis의 옵션별로 연산이 일어나는 것과, 가장 많이 헷갈리는 DataFrame.apply()함수에서의 예시를 통해 판다스에서의 axis 개념에 대해 정리해 보겠습니다.
  • 일단 예제를 위한 데이터를 만들어 보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 필요 라이브러리 불러오기

import pandas as pd

import numpy as np

  

# 데이터 입력

data = pd.DataFrame({

    '음식': ['김치볶음밥', '짜장면', '짬뽕', '탕수육', '볶음우동', '볶음밥', '울면', '양장피', '팔보채'],

    '가격': [7000, 8000, 9000, 15000, 8000, 7000, 8500, 16000, 18000],

    '양': [350, 500, 550, 600, 450, 400, 500, 650, 700],

    '열량': [600.0, 950.0, 1100.0, 1200.0, 800.0, 700.0, 850.0, 1300.0, 1400.0],

    '할인률': [0.1, 0.15, 0.2, 0.25, 0.15, 0.1, 0.2, 0.3, np.nan],

    '세일가': [6300.0, 6800.0, 7200.0, 11250.0, 6800.0, 6300.0, 6800.0, 11200.0, np.nan],

    '원산지': ['국내산', '중국산', '중국산', '국내산', '국내산', '국내산', '중국산', '국내산', '국내산'],

    '맛': ['매콤', '달콤', '매콤', '달콤', '짭짤', '짭짤', '매콤', '달콤', '달콤'],

    '인기': ['높음', '중간', '중간', '높음', '중간', '낮음', '낮음', '높음', '높음']

})

  

df = data.copy() # 여분 데이터 생성

  

data # 결과 출력

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
음식가격열량할인률세일가원산지인기
0김치볶음밥7000350600.00.106300.0국내산매콤높음
1짜장면8000500950.00.156800.0중국산달콤중간
2짬뽕90005501100.00.207200.0중국산매콤중간
3탕수육150006001200.00.2511250.0국내산달콤높음
4볶음우동8000450800.00.156800.0국내산짭짤중간
5볶음밥7000400700.00.106300.0국내산짭짤낮음
6울면8500500850.00.206800.0중국산매콤낮음
7양장피160006501300.00.3011200.0국내산달콤높음
8팔보채180007001400.0NaNNaN국내산달콤높음

일반적인 판다스에서의 axis가 가지는 의미

✔️ axis = 0 👉 axis = ‘index’ 를 의미합니다.

  • axis = 0 을 입력할 경우 각 열(column)을 기준으로 각각의 행(row)이 가진 값에 대해 수직적으로 연산이 적용 됩니다.
  • 즉, DataFrame의 각 열(column)을 독립적으로 취급해, 그 열(column)에 속한 모든 행(row)의 데이터에 대해 연산을 수행합니다.
    • 예를 들어 data.sum(axis = 0)은 data라는 DataFrame의 모든 열(column)이 가지고 있는 각각의 행(row)이 가지고 있는 값의 합계(sum)을 계산합니다.

정리

  1. axis = 0 = ‘index’ 에서 ‘index’는 연산할 값을 의미합니다.
  2. axis = 0 은 각 열(column)이 가진 모든 행(row)에 대해 연산을 수행한다는 것을 의미합니다.
  3. 열(column)이 가진 모든 행(row)를 연산하느 것이므로 수직적 연산 이라고 합니다.

예제코드 (axis =0) 및 연산 과정

1
2
3
data.sum(axis=0) # 각 열(column)이 가진 모든 row의 값에 대해 합계를 구합니다.


음식     김치볶음밥짜장면짬뽕탕수육볶음우동볶음밥울면양장피팔보채

가격                            96500

양                              4700

열량                           8900.0

할인률                            1.45

세일가                         62650.0

원산지     국내산중국산중국산국내산국내산국내산중국산국내산국내산

맛                매콤달콤매콤달콤짭짤짭짤매콤달콤달콤

인기               높음중간중간높음중간낮음낮음높음높음

dtype: object

  • 위와 같이 data의 각각의 컬럼이 가진 행(row)의 값들을 sum으로 모두 더한 결과를 출력합니다.

  • 전체의 DataFrame이라고 보는게 헷갈린다면 특정 컬럼 하나를 지정해서 보면 조금 더 이해가 쉬울 수 있습니다.
  • ‘가격’ 컬럼에 대해서만 axis = 0 으로 sum연산을 한 결과를 살펴보겠습니다.
    • data['가격'].sum(axis=0) 은 df라는 DataFrame의 ‘가격’이라는 열(column)의 모든 행(row = 값)의 합계(sum)을 계산합니다.
1
2
3
data['가격'].sum(axis=0)


96500

✔️ axis = 1 👉 axis = ‘column’ 를 의미합니다.

  • axis = 1 을 입력할 경우 각 행(row)을 기준으로 각각의 열(column)이 가진 값에 대해 수평적으로 연산이 적용 됩니다.

  • 즉, DataFrame의 각 행(row)를 독립적으로 취급하여, 그 행(row)에 속한 모든 열(column)에 데이터에 대해 연산을 수행합니다.

    • 예시 코드로는 동일하게 data.sum(axis = 1) 을 사용하겠습니다.
    • axis = 0 일때와 동일한 결과로 차이를 보여주기 위해 숫자형 데이터를 모두 문자열로 변경한 뒤 진행하겠습니다.
    • sum이라는 함수는 ‘문자열 + 문자열’ 또는 ‘숫자 + 숫자’ 처럼 같은 데이터타입의 값들간의 SUM만 가능하기 때문에 문자열로 모두 변경했습니다.

정리

  1. axis = 1 = ‘column’ 에서 ‘column’은 연산할 값을 의미합니다.
  2. 데이터 프레임에서 각 행(row)이 가진 모든 열(column)의 값에 대해 연산을 수행한다는 것을 의미합니다.
  3. 행(row)에 있는 모든 열(column)을 연산하느 것이므로 수평적 연산 이라고 합니다.

예제코드 (axis =1) 및 연산 과정

1
2
3
4
5
6
7
8
9
10
11
# axis = 0 일때와 동일한 결과로 차이를 보여주기 위해 숫자형 데이터를 모두 문자열로 변경

# 모든 컬럼을 object 타입으로 변경

data = data.astype('str')

  

data.sum(axis=1)


0      김치볶음밥7000350600.00.16300.0국내산매콤높음

1       짜장면8000500950.00.156800.0중국산달콤중간

2        짬뽕90005501100.00.27200.0중국산매콤중간

3    탕수육150006001200.00.2511250.0국내산달콤높음

4      볶음우동8000450800.00.156800.0국내산짭짤중간

5        볶음밥7000400700.00.16300.0국내산짭짤낮음

6         울면8500500850.00.26800.0중국산매콤낮음

7     양장피160006501300.00.311200.0국내산달콤높음

8         팔보채180007001400.0nannan국내산달콤높음

dtype: object


  • 이와 같이 axis = 0 일때는 수직연산, axis = 1일때는 수평연산 을 하는 것이 pandas에서의 연산에서의 기본 설정입니다.
  • 이러한 연산이 적용되는 함수들은 아래와 같습니다.
    - sum() : 각 행/열의 합계 계산
    - mean() : 각 행/열의 평균 계산
    - median() : 각 행/열의 중앙값 계산
    - min() : 각 행/열의 최소값 찾기
    - max() : 각 행/열의 최대값 찾기
    - std() : 각 행/열의 표준편차 계산
    - var() : 각 행/열의 분산 계산
    - quantile() : 각 행/열의 분위수 계산
    - cumsum() : 각 행/열의 누적합 계산
    - cumprod() : 각 행/열의누적곱 계산
    - cummax() : 각 행/열의 누적 최대값 계산
    - cummin() : 각 행/열의 누적 최소값 계산

✳️ 정리

  • 판다스에서 쓰이는 axis는 연산의 방향으로 받아들이지만, 실제로 적용을 하는것은 연산의 ‘대상’ 으로 보는 것이 이해에 더 직관적입니다.
    • axis = 0일때는 행방향에 대한 연산이지만 그 대상은 독립적인 개별 컬럼의 모든 행 이므로 행에 대한 연산을 하도록 하는 것입니다.
    • axis = 1이래는 열방향에 대한 연산이지만 그 대상은 독립적인 개별 행에 매칭되는 모든 컬럼의 값 이므로 컬럼에 대한 연산을 하는 것입니다.
  • 인트로 부분에서 설명한 것처럼 혼동의 원인이 되는 주요 내용들을 도식화 하여 정리하면 아래와 같습니다.


Outro.

오늘은 판다스에서 가장 많이 헷갈리는 부분중 하나인 index의 값에 따른 연산의 적용방향에 대해 정리해봤습니다.
다른 한가지 더 헷갈리는게 apply() 함수에서의 연산을 할때 인데요, 같은 apply() 함수여도 DataFrame에 직접 적용하느냐, 별개의 행이나 열을 지정해서 Series 형태에 적용하느냐에 따라 사용방법이 조금 달라질 수 있습니다.
다음 포스팅에서는 이 부분에 대해서 정리해 보도록 하겠습니다.

댓글남기기