[pandas] map,apply,applymap 비교

Numpy & Pandas
Author

신호연

Published

March 17, 2023

Import

sdasdaksldjklsdjklasjdklj dasmkdlmsakldmklsadmkls

import numpy as np
import pandas as pd

pd.Series.map

  • map은 Series의 method로 mapping(또는 function)을 통해 Series에 있는 각각의 값다른 값으로 바꾼다.
  • Note : Series에 있는 각각의 값이 elementwise로 함수(mapping)에 입력이 되어 여러번 계산된다고 생각하면 편하다.
  • Parameters
    • arg : function,dict,Series…
  • Returns
    • Series

Data

s = pd.Series(["cat","dog",np.nan,"rabbit"])

arg가 dict인 경우

s.map({"cat":"kitten","dog":"puppy"})
0    kitten
1     puppy
2       NaN
3       NaN
dtype: object
  • Series의 값 중 dict의 key와 일치하는 값이 없으면 NaN으로 바뀜.

arg가 Series인 경우

s2 = pd.Series(["lion","elephant","dog",np.nan])
s.map(s2)
0    NaN
1    NaN
2    NaN
3    NaN
dtype: object

arg가 function인 경우

s.map(lambda x : "I am a {}".format(x))
0       I am a cat
1       I am a dog
2       I am a nan
3    I am a rabbit
dtype: object

잘못된 사용 예시

s = pd.Series([0.1,3,2,0.4])
s.map(lambda x : sum(x))
>>> TypeError: 'float' object is not iterable
  • 각각의 값(여기선 float)이 따로따로 함수(mapping)이 입력된다. 하지만 sum함수는 float형을 input으로 할 수 없으므로 오류 발생함.(float형은 iterable하지 않음)
s = pd.Series([0.3,2,0.4,5])
s.map(np.var)
0    0.0
1    0.0
2    0.0
3    0.0
dtype: float64
  • 오류가 뜨지 않으나 원하던 동작이 아니다. 각각의 변수에 대해서 평균값을 구하려 했겠지만 각각의 값에 mean이 되므로 그 값 자체이다.

pd.DataFrame.apply

  • apply는 DataFrame의 method로 DataFrame의 축을 따라서 함수를 적용한다.
  • Note : DataFrame의 apply는 vector(column,row)단위로 함수에 입력된다.(map이나 applymap은 element들이 함수의 입력이 된다.)
  • Parameters
    • func : 각각의 column,row(vector)에 적용되는 함수
    • axis : 0이면 row에 1이면 column애 적용
  • Returns
    • Series or DataFrame

Data

n1 = pd.Series([0.1,4,0.35,2])
n2 = pd.Series([0.3,0.4,3,-5])
df = pd.DataFrame({"n1":n1,"n2":n2})
df
n1 n2
0 0.10 0.3
1 4.00 0.4
2 0.35 3.0
3 2.00 -5.0

column에 function 적용

  • column vector에 함수 적용한다고 생각하자.
df.apply(func = lambda x : sum(x)/len(x),axis=0)
n1    1.6125
n2   -0.3250
dtype: float64
df.apply(np.mean,axis=0)
n1    1.6125
n2   -0.3250
dtype: float64
#vector에 elementwise**2
#np.array를 **2하면 모든 원소가 제곱되는 것과 같다.
df.apply(func = lambda x : x ** 2,axis=0)
n1 n2
0 0.0100 0.09
1 16.0000 0.16
2 0.1225 9.00
3 4.0000 25.00
#vector에 elementwise로 sin취함.
df.apply(func = lambda x : np.sin(x),axis=0)
n1 n2
0 0.099833 0.295520
1 -0.756802 0.389418
2 0.342898 0.141120
3 0.909297 0.958924

row에 function 적용

  • row vector에 함수 적용.
df.apply(sum,axis=1)
0    0.40
1    4.40
2    3.35
3   -3.00
dtype: float64
df.apply(np.sin,axis=1)
n1 n2
0 0.099833 0.295520
1 -0.756802 0.389418
2 0.342898 0.141120
3 0.909297 0.958924
#vector에 elementwise**2
#np.array를 **2하면 모든 원소가 제곱되는 것과 같다.
df.apply(func = lambda x : x ** 2,axis=1)
n1 n2
0 0.0100 0.09
1 16.0000 0.16
2 0.1225 9.00
3 4.0000 25.00

pd.DataFrame.applymap

  • applymap은 DataFrame의 method로 mapping(또는 function)을 통해 DataFrame에 있는 각각의 값다른 값으로 바꾼다.
  • Note : DataFrame에 있는 각각의 값이 elementwise로 함수(mapping)에 입력되어 여러번 계산된다고 생각하면 편하다.
  • Parameters
    • func
  • Returns
    • DataFrame

Data

n1 = pd.Series([0.1,4,0.35,2])
n2 = pd.Series([0.3,0.4,3,-5])
df = pd.DataFrame({"n1":n1,"n2":n2})
df
n1 n2
0 0.10 0.3
1 4.00 0.4
2 0.35 3.0
3 2.00 -5.0

올바른 사용

df.applymap(lambda x : "값은 {}".format(x))
n1 n2
0 값은 0.1 값은 0.3
1 값은 4.0 값은 0.4
2 값은 0.35 값은 3.0
3 값은 2.0 값은 -5.0
df.applymap(lambda x : len(str(x)))
n1 n2
0 3 3
1 3 3
2 4 3
3 3 4
df.applymap(lambda x : x ** 2)
n1 n2
0 0.0100 0.09
1 16.0000 0.16
2 0.1225 9.00
3 4.0000 25.00

잘못된 사용

df.applymap(lambda x : sum(x))
>>> TypeError: 'float' object is not iterable
  • Series의 map method와 마찬가지로 DataFrame의 applymap method도 각각의 값(여기선 float)이 따로따로 함수(mapping)에 입력된다. 그러므로 sum함수에서 오류가 발생한다.
df.applymap(lambda x : np.mean(x))
n1 n2
0 0.10 0.3
1 4.00 0.4
2 0.35 3.0
3 2.00 -5.0
  • 오류가 뜨지 않으나 원하던 동작이 아니다. 각각의 변수에 대해서 평균값을 구하려 했겠지만 각각의 값에 mean이 되므로 그 값 자체이다.