본문 바로가기
Python/Pandas

객체간의 연산 add, sub, mul, div-pandas(24)

by 콩돌 2020. 4. 5.
반응형

파이썬 버전 3.7 기준

pandas 버전 0.25.1 기준



 객체간의 연산 add, sub, mul, div


본 포스팅에서는 pandas에서 객체간의 연산과 메서드를 통한 누락데이터 처리에 대해 설명한다.


 객체간의 연산


pandas와 data structure 간에 연산을 수행하기 위해, 두 가지 중요한 키포인트가 있다.

  ○ 브로드캐스팅(broadcasting) 거동 

    ▷ 높은 차원과 낮은 차원객체 간의 연산 수행 시

  ○ 계산시 누락데이터(missing data)의 처리


여기서는 위의 이슈들을 어떻게 다루는지 살펴볼 것이다. 


  연산 메서드 개요

DataFrame은 객체간의 이항 연산(binary operation)을 처리하기 위해 다양한 메서드들을 가진다.

  ○ add(), sub(), mul(), div(), pow()

  ○ radd(), rsub()


※ +,-,*,/와 같은 연산자와의 차이?

  A+B와 A.add(B)는 동일한 연산을 수행한다.

  다만, 차이점으로는 add()와 같은 메서드를 사용할 경우 메서드에서 제공하는 옵션을 사용하여 좀 더 디테일한 연산을 수행할 수 있으며, 해당 옵션들에 대해서는 아래에 설명한다.

  

연산 메서드의 간단한 사용 형식은 다음과 같다.


연산 메서드 사용 형식)

result= object1.operation(object2, axis='columns', fill_value=None)


여기서 operation은 연산 메서드를 입력받는다.

axis는 브로드캐스팅을 수행할 시 브로드캐스팅이 되는 방향을 입력받는다.

fill_value는 매칭이 되지 않는 데이터들에 어떤 값을 입력하여 연산을 수행할지 입력받는다.


위의 메서드를 통한 연산을 수행할 때

  ○ 데이터를 매칭시켜 각 요소끼리 대응(매칭, matching)시켜 연산을 수행할 수 있다.

  ○ 브로드캐스팅을 시켜 행 혹은 열마다 다른 값으로 연산을 수행시키게 하는 것이 가능하다.


※ 브로드캐스팅(broadcasting)?

  쉽게 설명하면 작은 차원의 배열을 큰 차원의 배열로 확장시켜 연산을 수행하는 것이다.

  세부사항은 여기(링크)를 참고하자.

  


  매칭(Matching)

위의 매서드들은 기본적으로 행과 열의 인덱스가 같은 값들을 매칭시겨 연산을 수행한다.

만약 메서드가 적용되는 객체(object1)에 대응하는 행과 열의 인덱스가 메서드를 적용하는 객체(object2)에 존재하지 않는다면 연산이 수행될 수 없으므로 NaN으로 처리된다.

  ○ 말이 어려운데 밑에 예제를 보자.

  ○ 이렇게 매칭되지 않는 데이터들에 대해서는 fill_value 값을 대응시켜 연산을 시키는 것이 가능하다.


아래 예제는 매칭이 어떻게 진행되는지 보여주는 예제이다.


매칭 예제)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np


# 예제용 배열 선언

In[4]: ex_df=pd.DataFrame(np.arange(0,12).reshape(4,3), columns=['a','b','c'])

In[5]: ex_df2=pd.DataFrame(np.arange(0,9).reshape(3,3), columns=['a','b','c'])


In[6]: ex_df

Out[6]: 

   a   b   c

0  0   1   2

1  3   4   5

2  6   7   8

3  9  10  11

In[7]: ex_df2

Out[7]: 

   a  b  c

0  0  1  2

1  3  4  5

2  6  7  8


# 메서드의 적용 예1 (매칭되지 않는 데이터 존재)

In[8]: ex_df.mul(ex_df2)

Out[8]: 

      a     b     c

0   0.0   1.0   4.0

1   9.0  16.0  25.0

2  36.0  49.0  64.0

3   NaN   NaN   NaN


# 메서드의 적용 예2 (매칭되지 않는 데이터 존재, fill_value 적용)

In[9]: ex_df.mul(ex_df2, fill_value=1)

Out[9]: 

      a     b     c

0   0.0   1.0   4.0

1   9.0  16.0  25.0

2  36.0  49.0  64.0

3   9.0  10.0  11.0



  브로드캐스팅(broadcasting)

위에서 언급했다시피 브로드캐스팅을 통해 행 혹은 열 별로 다른 값으로 연산시키는 것이 가능하다.

  ○ axis 키워드인자를 활용하자.

 

다음 예제는 위의 메서드를 활용하여 브로드캐스팅을 수행하는 것을 보여주는 예제이다.


브로드캐스팅 예제)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np


# 예제용 배열 선언

In[10]: ex_df=pd.DataFrame(np.arange(0,12).reshape(4,3), columns=['a','b','c'])

In[11]: ex_df3=ex_df['a']

In[12]: ex_df4=ex_df.loc[1]


In[13]: ex_df

Out[13]: 

   a   b   c

0  0   1   2

1  3   4   5

2  6   7   8

3  9  10  11

In[14]: ex_df3

Out[14]: 

0    0

1    3

2    6

3    9

Name: a, dtype: int32

In[15]: ex_df4

Out[15]: 

a    3

b    4

c    5

Name: 1, dtype: int32


# 메서드 적용 예 3 (행방향 브로드캐스팅 적용)

In[16]: ex_df.mul(ex_df3, axis=0)

Out[16]: 

    a   b   c

0   0   0   0

1   9  12  15

2  36  42  48

3  81  90  99


메서드 적용 예 4 (열방향 브로드캐스팅 적용)

In[17]: ex_df.mul(ex_df4, axis=1)

Out[17]: 

    a   b   c

0   0   4  10

1   9  16  25

2  18  28  40

3  27  40  55



  멀티인덱스에서의 연산 수행

멀티인덱스에서 연산을 수행할때에는 level 변수를 활용하여 DataFrame의 특정 레벨에 연산을 적용시킬 수 있다.

 

멀티인덱스의 연산 예제)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np


# 예제용 배열 선언

In[18]: ex_df=pd.DataFrame(np.arange(0,12).reshape(4,3), columns=['a','b','c'])

In[19]: ex_df3=ex_df['a']

In[20]: ex_df.index= pd.MultiIndex.from_tuples([('A', 0), ('A', 1), ('B', 2), ('B', 3)], names=['first', 'second'])


In[21]: ex_df
Out[21]: 
              a   b   c
first second           
A     0       0   1   2
      1       3   4   5
B     0       6   7   8
      1       9  10  11

In[22]: ex_df3
Out[22]: 
0    0
1    3
2    6
3    9

# 멀티인덱스로의 연산 메서드 적용

In[23]: ex_df.sub(ex_df3, axis=0, level='second')
Out[23]: 
              a  b  c
first second         
A     0       0  1  2
      1       0  1  2
B     0       6  7  8
      1       6  7  8



  나눗셈의 몫과 나머지를 구하는 divmod 함수

Series와 index에는 divmod() 내장 함수를 적용시킬 수 있다. 

  ○ DataFrame에는 해당 함수를 적용하지 못한다.

해당 함수는 나눗셈의 몫과 나머지를 동시에 출력시켜준다.

  ○ 이 함수의 값은 튜플형태로 출력된다.

  ○ 이 함수에 대한 자세한 설명은 여기(링크)에 있다.


divmod 함수 적용 예제)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np


# 예제용 Series 생성

In[24]: ex_s = pd.Series(np.arange(10))


In[25]: ex_s

Out[25]: 

0    0

1    1

2    2

3    3

4    4

5    5

6    6

7    7

8    8

9    9

dtype: int32


# pandas와 numpy의 import

In[26]: div, rem = divmod(ex_s, 5)


In[27]: div

Out[27]: 

0    0

1    0

2    0

3    0

4    0

5    1

6    1

7    1

8    1

9    1

dtype: int32


In[28]: rem

Out[28]: 

0    0

1    1

2    2

3    3

4    4

5    0

6    1

7    2

8    3

9    4

dtype: int32

 


  누락데이터에 대한 연산 처리 

Series와 DataFrame에서 산술연산 함수들은 fill_value라는 옵션을 가진다. 

이 옵션은 한 위치서 값이 누락되어 있을 때 대체할 수 있는 값을 채운다.

  ○ 만약 fill_value를 이용하여 처리를 하지 않는다면 연산의 값은 NaN값으로 처리된다.

  ○ 관련 내용은 밑에 예제를 보자.

만약 연산 이후에 누락 값을 처리하고 싶다면 fillna 함수를 이용하는 것이 좋다.


fill_value 옵션 사용 전후 비교 예제)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np


# 예제용 배열 선언

In[29]: ex_df=pd.DataFrame(np.arange(0,12).reshape(4,3), columns=['a','b','c'])

In[30]: ex_df5=pd.DataFrame([[1,1,1],[np.nan,np.nan,np.nan],[1,1,1],[1,1,1]], columns=['a','b','c'])

In[31]: ex_df
Out[31]: 
   a   b   c
0  0   1   2
1  3   4   5
2  6   7   8
3  9  10  11
In[32]: ex_df5
Out[32]: 
     a    b    c
0  1.0  1.0  1.0
1  NaN  NaN  NaN
2  1.0  1.0  1.0
3  1.0  1.0  1.0


# fill_value 없이 연산 수행

In[33]: ex_df.add(ex_df5)

Out[33]: 

      a     b     c

0   1.0   2.0   3.0

1   NaN   NaN   NaN

2   7.0   8.0   9.0

3  10.0  11.0  12.0


# fill_value 입력 후 연산 수행

In[34]: ex_df.add(ex_df5, fill_value=-999)

Out[34]: 

       a      b      c

0    1.0    2.0    3.0

1 -996.0 -995.0 -994.0

2    7.0    8.0    9.0

3   10.0   11.0   12.0

 


 각 연산메서드 세부사항


add(), sub(), mul(), div(), pow()와 같은 메서드는 사실상 연산만 다르지 동일한 옵션을 가진다. 

  ○ add() : 덧셈을 수행한다 (+)

  ○ sub() : 뺄셈을 수행한다 (-)

  ○ mul() : 곱셈을 수행한다 (*)

  ○ div() : 나눗셈을 수행한다 (/)

  ○ pow() : 지수연산을 수행한다 (**)


메서드에 대한 세부사항은 add() 메서드를 예를들어 설명하도록 한다.


 DataFrame.add(self, other, axis='columns', level=None, fill_value=None)


other: scalar, sequence, Series, or DataFrame

연산을 수행할 데이터를 입력받는다.

하나의 단일값, Series, 시퀀스형 자료형, DataFrame 등을 입력받을 수 있다.


axis: {0 or ‘index’, 1 or ‘columns’}

브로드캐스팅을 수행할 시에 어느 쪽 방향으로 연산을 수행할지 결정한다.

0 혹은 'index'를 입력받을 경우 동일 index를 가지는 값에 대해 브로드캐스팅을 수행하며,

1 혹은 'columns'를 입력받을 경우는 동일 columns 주소를 가지는 값에 대해 브로드캐스팅을 수행한다. 


level: int or label

멀티인덱스에서 브로드캐스팅을 수행할 레벨을 선택한다.


fill_value: float or None, default None

데이터가 없거나 NaN과 같이 누락 데이터들에 대해 이 옵션에 입력된 값을 연산 데이터로 사용한다.




 

 

 

 

 참고자료

  https://pandas.pydata.org/pandas-docs/stable/getting_started/basics.html

  https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.add.html

  https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sub.html

  https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.mul.html

  https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.div.html

 

 

 

 



반응형

댓글