별의 공부 블로그 🧑🏻‍💻
728x90
728x170

판다스의 주요 기능

  • head tail 메소드를 사용하여 시리즈나 데이터프레임의 내용을 살펴볼 수 있다.
>>> ser = pd.Series(np.random.randn(1000))

>>> ser.head()
0    0.800680
1   -1.002317
2    0.808993
3    0.648255
4   -1.096188
dtype: float64

>>> ser.tail(3)
997    0.905623
998   -0.383506
999   -0.104021
dtype: float64

 

  • 판다스는 메타데이터에 접근하도록 많은 속성을 가지고 있다.
  • shape 속성으로 객체의 축 차원을 알 수 있다.
  • 축 라벨을 확인하기 위해 시리즈에는 index, 데이터프레임의 행에는 index, 그리고 열에는 columns 속성을 사용할 수 있다.
ind = pd.date_range('1/1/2021', periods=5)
ser = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
df = pd.DataFrame(np.random.randn(5, 3), index=ind, columns=['A', 'B', 'C'])
df[:2]

 

판다스 객체 이진 연산

  • 판다스 데이터 구조 사이에 이진 연산을 할 때 고려해야 하는 2가지 사항
    • 데이터프레임과 시리즈 객체들 사이에서 연산을 할 때 브로드캐스팅.
    • 계산 시 손실 데이터의 처리 방법
  • 데이터프레임
    • 이진 연산을 위한 add(), sub(), mul(), div() 메소드와 이와 관련된 radd(), rsub() 등의 함수를 갖는다. 
    • 브로드캐스팅 연산 시에는 주로 시리즈를 입력한다.
    • 함수를 적용할 때는 축 키워드에서 지정해 해당 index나 열에 맞게 사용한다.
df = pd.DataFrame({'one' : pd.Series(np.random.randn(2), index=['a', 'b']),
                  'two' : pd.Series(np.random.randn(3), index=['a', 'b', 'c']),
                  'three' : pd.Series(np.random.randn(2), index=['b', 'c'])})
df

 

>>> df.iloc[1]
one      0.653086
two      0.672652
three   -2.003373
Name: b, dtype: float64

>>> df['two']
a    0.540905
b    0.672652
c   -1.112673
Name: two, dtype: float64

>>> row = df.iloc[1]
>>> col = df['two']

 

  • 이번에는 축의 값을 다르게 하여 sub() 메소드를 적용해본다.
df.sub(row, axis='columns')
더보기

 

  • df 의 열 축을 기준으로 각 열의 값에서 인덱스 b의 값을 빼는 연산이다.

 

df.sub(col, axis=0)
더보기

 

  • axis=1을 입력해도 axis='columns'와 같은 연산 결과를 얻는다.
  • axis=0을 입력하면 axis='index'와 같은 연산 결과를 얻을 수 있다.

 

  • 시리즈와 데이터프레임의 산술 연산 함수들은 매개 변수 fill_value 옵션을 가진다.
    • 이 옵션으로 어떤 위치의 손실 값을 대체할 수 있지만, 최대 1개의 손실 값만을 대체할 수 있다.
d = {'one' : [1., 2., np.nan], 'two' : [3., 2., 1.], 'three' : [np.nan, 1., 1.]}
df = pd.DataFrame(d, index=list('abc'))
df

 

d1 = {'one' : pd.Series([1., 2.], index=['a', 'b']),
     'two' : pd.Series([1., 1., 1.], index=['a', 'b', 'c']),
     'three' : pd.Series([2., 2., 2.], index=['a', 'b', 'c'])}
df1 = pd.DataFrame(d1)
df1

 

  • 2개의 데이터프레임 객체를 더할 때, 두 데이터프레임에 손실 값이 있으면 손실 값을 0으로 바꾸어 연산할 수 있다.
    • 또한, fillna()를 사용하여 손실 값을 다른 값으로 변환할 수 있다.
df + df1

 

df.add(df1, fill_value=0)

 

DataFrame.sub 메소드를 사용하는 연산 예제
df = pd.DataFrame({'angles' : [0, 3, 4], 'degrees' : [360, 180, 360]}, index=['circle', 'triangle', 'rectangle'])
df

 

df + 1

 

df - [1, 2]    # 연산자를 이용해 리스트 빼기

 

df.sub([1, 2], axis='columns')    # sub() 메소드에서 축을 지정하여 리스트 빼기

 

df1 = df.sub(pd.Series([1, 2, 3], index=['circle', 'triangle', 'rectangle']), axis='index')
df1
더보기

 

  • df와 시리즈 객체의 인덱스가 동일하므로 서로 뺄셈 연산을 할 수 있다.

 

 

요약과 통계 연산

  • 시리즈데이터프레임에는 요약과 통계 연산을 위한 많은 메소드가 있다.
    • 이 메소드들은 ndarray.{sum, std 등}에서 axis 인수를 가지는데, 이 인수는 이름이나 정수 형태로 입력한다.
  • 통계 처리를 위한 연산을 할 때는 다음과 같은 손실 데이터 처리 방법을 고려한다.
    • 데이터를 더할 때 손실 값(NA)들은 0으로 취급한다.
    • 데이터가 모두 NA이면 그 결과는 0이다.
    • cumsum() cumprod()는 기본으로 손실 값들을 무시하지만 결과 배열에서는 유지한다.

 

d = {'one' : [1., 2., np.nan], 'two' : [3., 2., 1.], 'three' : [np.nan, 1., 1.]}
df = pd.DataFrame(d, index=list('abc'))
df

 

>>> df.mean(0)
one      1.5
two      2.0
three    1.0
dtype: float64

>>> df.mean(1)
a    2.000000
b    1.666667
c    1.000000
dtype: float64

 

  • skipna 옵션을 사용하여 손실 데이터를 배제할지 결정할 수 있다.
    • 기본값은 True 이다.
>>> df.sum(0, skipna=False)
one      NaN
two      6.0
three    NaN
dtype: float64

>>> df.sum(1, skipna=True)
a    4.0
b    5.0
c    2.0
dtype: float64

 

  • 브로드캐스팅산술 연산을 함께 처리할 수 있으면 '평균이 0, 표준 편차가 1인 정규 분포' 와 같은 다양한 통계 절차를 입력할 수 있다.
>>> df.std()
one      0.707107
two      1.000000
three    0.000000
dtype: float64

>>> df.std(axis=1)    # 기본값은 ddof=1
a    1.414214
b    0.577350
c    0.000000
dtype: float64

>>> np.std(df, axis=1)    # 기본값은 ddof=0
a    1.000000
b    0.471405
c    0.000000
dtype: float64

>>> np.std(df, ddof=1, axis=1)
a    1.414214
b    0.577350
c    0.000000
dtype: float64

>>> df[['one', 'two', 'three']].std()
one      0.707107
two      1.000000
three    0.000000
dtype: float64

 

  • 누적합을 계산하는 cumsum() 메소드는 다음과 같이 적용할 수 있다.
df.cumsum()

 

  • mean(), std()sum()과 같은 넘파이 함수들은 시리즈 입력값에 있는 손실 값을 기본으로 제외한다.
>>> np.mean(df['one'])
1.5

 

  • Series.nunique() 는 시리즈에서 손실 값을 제외한 유일한 요소의 개수를 반환한다.
>>> ser = pd.Series(np.random.randn(500))
>>> ser[20:500] = np.nan
>>> ser[10:20] = 5
>>> ser.nunique()
11

 

  • describe() 메소드는 데이터프레임의 행이나 시리즈에서 다양한 요약 통계를 계산할 수 있다.
>>> ser = pd.Series(np.random.randn(1000))
>>> ser[::2] = np.nan
>>> ser.describe()

count    500.000000
mean      -0.009480
std        1.002857
min       -2.859723
25%       -0.678066
50%       -0.088924
75%        0.722685
max        2.910388
dtype: float64

 

  • 다음은 데이터프레임의 행에 다양한 요약 통계를 계산한다.
df = pd.DataFrame(np.random.randn(1000, 4), columns=['a', 'b', 'c', 'd'])
df.iloc[::2] = np.nan
df.describe()

 

  • 출력에 포함할 특정 백분위수를 선택할 수 있다.
    • 확률 통계에서 분위수(Quantile)는 범위나 샘플의 관찰 구간을 같은 확률로 가진 연속 구간으로 나누거나, 동등한 크기의 구간으로 구분하는 지점이다.
      • 사분위수(Quantile)2사분위수중앙값(Median)이라 한다.
>>> ser.describe(percentiles=[0.05, 0.25, .75, .95])
count    500.000000
mean      -0.009480
std        1.002857
min       -2.859723
5%        -1.608900
25%       -0.678066
50%       -0.088924
75%        0.722685
95%        1.588207
max        2.910388
dtype: float64

 

  • 수치가 아닌 객체describe() 메소드를 적용하면 다음 예와 같이 유일 값의 수와 가장 빈번히 발생하는 값들의 간단한 요약을 반환한다.
>>> ser = pd.Series(['a', 'a', 'b', 'c', 'c', np.nan, 'c', 'd'])
>>> ser.describe()
count     7
unique    4
top       c
freq      3
dtype: object

 

  • 범주형과 수치가 혼합된 타입의 데이터프레임 객체에 describe() 메소드를 적용하면 수치로 이루어진 열만 반환한다.
df = pd.DataFrame({'a' : ['Yes', 'Yes', 'No', 'No'], 'b' : range(4)})
df.describe()

 

  • describe()includeexclude 인수를 적용할 수 있다.
    • exclude 에는 적용하지 않을 열을 전달한다.
df.describe(include=['object'])

 

df.describe(include=['number'])

 

df.describe(include='all')
더보기

 

  • 객체 a와 수치 b에 대해 인수 all을 적용하면 객체와 수치 모두를 포함한다.

 

  • idxmax() idxmin() 메소드는 시리즈와 데이터프레임의 요소가 최댓값과 최솟값을 가지는 인덱스의 라벨을 계산한다.
    • 넘파이의 argmax() argmin() 메소드와 동일하다.
>>> ser = pd.Series(np.random.randn(5))
>>> ser
0   -1.658467
1    0.910685
2    2.556914
3    0.242846
4   -0.095138
dtype: float64

>>> ser.idxmin(), ser.idxmax()    # 해당 값이 있는 인덱스를 출력한다.
(0, 2)

 

  • idxmax() idxmin() 메소드의 을 인수로 전달하여 실행할 수 있다.
df = pd.DataFrame(np.random.randn(4, 3), columns=['A', 'B', 'C'])
df

 

>>> df.idxmin(axis=0)
A    1
B    2
C    1
dtype: int64

>>> df.idxmin()
df.idxmin()
df.idxmin()
A    1
B    2
C    1
dtype: int64

>>> df.idxmax(axis=1)
0    C
1    C
2    A
3    B
dtype: object

 

  • 최솟값과 최댓값에 일치하는 행이나 열이 다수라면 idxmin()idxmax()첫 번째로 일치하는 인덱스를 반환한다.
df1 = pd.DataFrame([2, 1, 1, 3, np.nan], columns=['A'], index=list('edcba'))
df1

 

>>> df1['A'].idxmin()
'd'

 

  • 시리즈 메소드인 value_counts()1차원 배열 값의 도수를 계산한다.
    • 이 메소드는 규칙적 배열에 사용할 수 있다.
>>> data = np.random.randint(0, 7, size=30)
>>> data
array([6, 5, 3, 0, 4, 1, 6, 2, 0, 5, 5, 3, 4, 0, 6, 5, 3, 3, 4, 1, 5, 6,
       0, 1, 0, 6, 6, 4, 4, 5])
       
>>> ser1 = pd.Series(data)
>>> ser1.value_counts()
6    6
5    6
0    5
4    5
3    4
1    3
2    1
dtype: int64

>>> pd.value_counts(data)
6    6
5    6
0    5
4    5
3    4
1    3
2    1
dtype: int64

 

  • 함수 cut()qcut()을 사용하면 연속하는 값들을 구간(bin)으로 나눌 수 있다.
    • 구간은 범주(Category)를 가지는 저장소로 이해할 수 있다.
  • cut() 함수
    • 데이터 값들을 개별적인 간격으로 나누어 구간으로 분할하거나 순서를 정렬할 때 사용한다.
    • 연속적인 값의 변수범주형 변수의 범위를 다룰 때 적용할 수 있다.
      • 예) 나이를 나이 범위의 그룹으로 변환
>>> pd.cut(np.array([1, 7, 5, 4, 6, 3]), 3)
[(0.994, 3.0], (5.0, 7.0], (3.0, 5.0], (3.0, 5.0], (5.0, 7.0], (0.994, 3.0]]
Categories (3, interval[float64, right]): [(0.994, 3.0] < (3.0, 5.0] < (5.0, 7.0]]

 

  • 인수 retbins=True를 입력하면 구간 값을 반환한다.
>>> pd.cut(np.array([1, 7, 5, 4, 6, 3]), 3, retbins=True)    # 구간 값을 반환
([(0.994, 3.0], (5.0, 7.0], (3.0, 5.0], (3.0, 5.0], (5.0, 7.0], (0.994, 3.0]]
 Categories (3, interval[float64, right]): [(0.994, 3.0] < (3.0, 5.0] < (5.0, 7.0]],
 array([0.994, 3.   , 5.   , 7.   ]))

 

  • 구간에 특정 라벨을 할당하여 labels 범주를 반환할 수 있다.
>>> pd.cut(np.array([1, 7, 5, 4, 6, 3]), 3, labels=['bad', 'medium', 'good'])
['bad', 'good', 'medium', 'medium', 'good', 'bad']
Categories (3, object): ['bad' < 'medium' < 'good']

 

  • labels=False 인수를 입력하면 범주형 시리즈나 정수 배열을 반환한다.
>>> pd.cut([0, 1, 1, 2], bins=4, labels=False)
array([0, 1, 1, 3], dtype=int64)

 

  • cut() 함수에 시리즈를 입력하면 categorical dtype시리즈를 반환한다.
>>> ser = pd.Series(np.array([2, 4, 6, 8, 10]), index=['a', 'b', 'c', 'd', 'e'])
>>> pd.cut(ser, 3)
a    (1.992, 4.667]
b    (1.992, 4.667]
c    (4.667, 7.333]
d     (7.333, 10.0]
e     (7.333, 10.0]
dtype: category
Categories (3, interval[float64, right]): [(1.992, 4.667] < (4.667, 7.333] < (7.333, 10.0]]

 

  • qcut() 함수
    • 분위(Quantile) 기반이산(Discretization) 함수
    • 순위나 샘플 분위에 기반하여 변수를 동등한 크기로 나눈다.
    • 범위 밖의 값들은 결과인 범주형 객체에서 NA가 된다.
>>> pd.qcut(range(5), 4)
[(-0.001, 1.0], (-0.001, 1.0], (1.0, 2.0], (2.0, 3.0], (3.0, 4.0]]
Categories (4, interval[float64, right]): [(-0.001, 1.0] < (1.0, 2.0] < (2.0, 3.0] < (3.0, 4.0]]

>>> pd.qcut(range(5), 3, labels=['good', 'medium', 'bad'])
['good', 'good', 'medium', 'bad', 'bad']
Categories (3, object): ['good' < 'medium' < 'bad']

>>> pd.qcut(range(5), 4, labels=False)
array([0, 0, 1, 2, 3], dtype=int64)

 

  • 다음을 통해 cut() 함수와 qcut() 함수의 차이를 확인할 수 있다.
    • cut() 함수는 구간 범위에 해당하는 길이가 동등하도록 나눈다.
    • qcut() 함수는 구간 범위에 해당하는 개수가 동등하도록 나눈다.
>>> pd.cut(np.random.randn(25), 5).value_counts()
(-2.237, -1.4]     3
(-1.4, -0.567]     5
(-0.567, 0.266]    9
(0.266, 1.098]     6
(1.098, 1.931]     2
dtype: int64

>>> pd.qcut(np.random.randn(25), 5).value_counts()
(-2.13, -1.146]     5
(-1.146, -0.625]    5
(-0.625, 0.123]     5
(0.123, 0.817]      5
(0.817, 2.108]      5
dtype: int64

 

 

함수 적용

  • 사용자 정의 함수나 다른 라이브러리에 속한 함수들을 판다스 객체에 적용할 때, 이 함수들은 다음과 같이 행, 열 또는 요소 단위의 데이터프레임이나 시리즈에 적용된다.
    • 테이블 형태의 함수를 적용 : pipe()
    • 행 또는 열 단위의 함수를 적용 : apply()
    • Aggregation API : agg() transform()
    • 요소 단위로 함수를 적용 : applymap()

 

테이블 형태의 함수 적용

  • 테이블 형태의 함수를 적용할 때는 데이터프레임이나 시리즈에 함수로 입력할 수 있다.
  • 함수를 체인(Chain) 형태로 호출해야 한다면 pipe() 메소드를 사용할 수 있다.
  • 시리즈나 데이터프레임, GroupBy 객체들을 여러 함수와 함께 연쇄적으로 묶을 때 .pipe를 사용한다.
# f(g(h(df), arg1=a), arg2=b, arg3=c)와 같이 사용하는 대신 다음과 같은 로직으로 작성한다.
(df.pipe(h)
    .pipe(g, arg1=a)
    .pipe(f, arg2=b, arg3=c)
)

 

  • 데이터에 pipe() 메소드를 이용해 사칙 연산을 수행할 수 있다.
data = pd.DataFrame([[1, 1, 1,], [2, 2, 2,], [3, 3, 3]], index=['A', 'B', 'C'], columns=['one', 'two', 'three'])
data

 

  • 생성된 data 객체에 사용자 정의 함수를 사용한 사칙 연산을 pipe() 메소드를 이용해 체인 형태로 묶어 실행한다.
def add(data, arg1):
    data1 = data + arg1
    return data1

def div(data1, arg2):
    data2 = data1 / arg2
    return data2

def mul(data2, arg3):
    data3 = data2 * arg3
    return data3

def sub(data3, arg4):
    data4 = data3 - arg4
    return data4

(data.pipe(add, arg1=2)       # data에 2를 더하기
     .pipe(div, arg2=3)       # data에 2를 더한 결과에 3으로 나누기
     .pipe(mul, arg3=5)       # 위 결과를 3으로 나눈 후 5를 곱하기
     .pipe(sub, arg4=1))      # 위 결과에서 1을 빼기

 

예제 : 가족 구성원들의 성별에 따라 평균 나이 구하기
df = pd.DataFrame()
df['name'] = ['jsun', 'jin', 'ujung', 'naeun', 'suho']
df['sex'] = ['female', 'male', 'female', 'female', 'male']
df['age'] = [84, 58, 53, 27, 18]
df

 

  • 데이터를 성별인 sex그룹화하고, 각 성별 그룹의 평균 나이를 연산하는 함수를 구성한다.
  • 또한, 모든 열 라벨을 대문자로 바꾼 후 데이터프레임 열에 동적 할당한다.
def mean_age_group(dataframe, col):
    return dataframe.groupby(col).mean()

def cap_column(dataframe):
    dataframe.columns = dataframe.columns.str.upper()
    return dataframe

 

(df.pipe(mean_age_group, col='sex')
    .pipe(cap_column))

 

  • 이처럼 pipe()는 여러 연산을 담당하는 다수의 함수를 순차적으로 연계해 처리함으로써 복잡한 연산 과정을 단순화하는 유용한 메소드이다.

 

행 또는 열 단위의 함수 적용

  • apply() 메소드는 axis 인수를 선택적으로 취하므로 이 메소드를 사용하면 데이터프레임의 행 또는 열에 함수를 적용할 수 있다.
data = [{'one' : 1.0, 'two' : 1.2}, {'one' : 0.5, 'two' : 1.1, 'three' : 0.7},
       {'one' : 0.7, 'two' : 0.9, 'three' : -1.6}, {'two' : 1.4, 'three' : -1.2}]
df = pd.DataFrame(data, index=list('abcd'))
df
더보기

 

  • df딕셔너리형 데이터로 구성된 리스트에서 데이터프레임 객체를 생성한다.

 

  • 앞 결과에 apply() 메소드를 사용해 np.mean을 적용하면 기본으로 을 중심으로 평균값을 구한다.
  • 인수 axis=1을 설정하면 을 기준으로 연산한다.
>>> df.apply(np.mean)
one      0.733333
two      1.150000
three   -0.700000
dtype: float64

>>> df.apply(np.mean, axis=1)
a    1.100000
b    0.766667
c    0.000000
d    0.100000
dtype: float64​
  • df에 apply() 메소드로 람다 함수를 적용하여 최댓값과 최솟값의 차이를 구할 수 있다.
>>> df.apply(lambda x: x.max() - x.min())
one      0.5
two      0.5
three    2.3
dtype: float64​

 

df.apply(np.cumsum)

 

df.apply(np.exp)

 

  • apply() 메소드에는 다음과 같이 문자열인 메소드 이름을 적용할 수도 있다.
>>> df.apply('mean')
one      0.733333
two      1.150000
three   -0.700000
dtype: float64

>>> df.apply('mean', axis=1)
a    1.100000
b    0.766667
c    0.000000
d    0.100000
dtype: float64

 

 

Aggregation API 함수 적용

  • Aggregaton API
    • 다중 종합 연산을 수행할 수 있도록 도와준다.
  • agg() 메소드
    • aggregation()의 약칭
    • 데이터프레임과 시리즈에 적용 가능할 수 있다.
    • 명시한 축에 1개 이상의 연산을 통합하여 실행하며, 반환된 객체의 차원이 축소된다.
  • transform() 메소드
    • 원형과 같은 크기의 Index 객체를 반환한다.
    • 하나보다는 여러 연산을 동시에 수행하도록 하며, Aggregation API와 유사하게 동작한다.

 

  • agg()로 행에 여러 함수를 종합하여 연산하기 위해 다음과 같이 df 객체를 생성한다.
df = pd.DataFrame([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9],
                   [np.nan, np.nan, np.nan]], columns=['A', 'B', 'C'])
df

 

df.agg(['sum', 'min'])

 

  • 메소드 agg()을 명시하지 않으면 각 열에 각기 다른 종합 연산을 실행한다.
  • axis='columns'인 경우 행의 평균을 구한다.
df.agg({'A' : ['sum', 'min'], 'B' : ['min', 'max']})

 

>>> df.agg("mean", axis="columns")
0    2.0
1    5.0
2    8.0
3    NaN
dtype: float64

 

  • Aggregation API를 사용해 종합 연산을 수행하기 위해 다음과 같이 데이터프레임을 생성한다.
adf = pd.DataFrame(np.random.randn(6, 3), columns=['A','B','C'], index=pd.date_range('7/1/2021', periods=6))
adf.iloc[2:4] = np.nan
adf

 

  • 단일 함수를 사용하는 방법은 apply() 메소드를 사용하는 방법과 동일하다.
  • 또한, 문자열인 메소드 이름을 전달할 수도 있다.
  • 이 연산들은 시리즈를 반환한다.
>>> adf.agg(np.sum)
A   -0.080577
B   -0.528719
C   -1.367696
dtype: float64

>>> adf.agg('sum')
A   -0.080577
B   -0.528719
C   -1.367696
dtype: float64

>>> adf.sum()
A   -0.080577
B   -0.528719
C   -1.367696
dtype: float64

 

  • 시리즈에 단일 종합 연산을 실행하면 스칼라 값을 반환한다.
>>> adf.A.agg('sum')
-0.08057672273092953

 

  • 복수의 함수로 종합 연산을 실행할 때 여러 인수를 리스트로 전달할 수 있다.
    • 전달한 함수는 연산 결과에서 데이터프레임의 행으로 나타난다.
adf.agg(['sum'])

 

  • 복수의 함수를 사용하면 복수의 행을 반환한다.
adf.agg(['sum', 'mean'])

 

  • 람다 함수를 입력하면 <lambda> 이름의 행을 반환한다.
>>> adf.A.agg(['sum', lambda x: x.mean()])
sum        -0.080577
<lambda>   -0.020144
Name: A, dtype: float64

 

  • 사용자 정의 함수를 입력하면 행에 그 함수의 이름을 반환한다.
def mymean(x):
    return x.mean()
>>> adf.A.agg(['sum', mymean])
sum      -0.080577
mymean   -0.020144
Name: A, dtype: float64

 

  • DataFrame.agg()로 각 열에 함수 이름을 딕셔너리형으로 전달하면 각 열에 해당 함수를 적용한다.
>>> adf.agg({'A': 'mean', 'B': 'sum'})
A   -0.020144
B   -0.528719
dtype: float64

 

  • 열 라벨에 유사 리스트로 함수를 전달하면 데이터프레임 형태로 출력된다.
adf.agg({'A': ['mean', 'min'], 'B': 'sum'})

 

  • transform() 메소드를 사용하면 데이터프레임에 람다 함수를 적용하여 연산할 수 있다.
df = pd.DataFrame({'A': range(3), 'B': range(1, 4)})
df

 

df.transform(lambda x: x + 1)

 

  • transform() 메소드에는 넘파이 함수, 문자열인 함수 이름 또는 사용자 정의 함수를 입력할 수 있으며, 전체 프레임을 반환한다.
adf.transform(np.abs)
더보기

 

  • np.abs 대신 abs 또는 lambda x: x.abs()를 입력해도 결과는 같다.
  • np.abs(adf)의 연산 결과와도 동일하다.

 

  • 시리즈에 함수 하나를 입력하면 단일 시리즈를 반환한다.
>>> adf.A.transform(np.abs)
2021-07-01    0.118335
2021-07-02    1.011351
2021-07-03         NaN
2021-07-04         NaN
2021-07-05    0.238513
2021-07-06    0.971750
Freq: D, Name: A, dtype: float64

 

  • 복수의 함수를 전달하면 멀티 인덱스를 가진 열로 이루어진 데이터프레임을 반환한다.
    • 첫 번째 레벨 : 원래 데이터프레임의 열 이름
    • 두 번째 레벨 : 변환하는 함수들의 이름
adf.transform([np.abs, lambda x: x + 1])

 

  • 복수의 함수를 시리즈로 입력하면 데이터프레임을 반환한다.
    • 결과의 열 이름은 변환 함수의 이름이다.
adf.A.transform([np.abs, lambda x: x + 1])

 

  • 함수들로 이루어진 딕셔너리를 전달하면 각 열마다 연산을 적용할 수 있다.
adf.transform({'A': np.abs, 'B': lambda x: x + 1})

 

  • 리스트가 있는 딕셔너리를 전달하면 각 열에 함수를 호출하여 연산을 실행하여 멀티 인덱스를 가진 데이터프레임을 생성한다.
adf.transform({'A': np.abs, 'B': [lambda x: x + 1, 'sqrt']})

 

요소 단위로 함수들을 적용

  • 데이터프레임에 applymap() 메소드로 사용자 정의 함수를 적용할 수 있다.
  • 시리즈에 사용자 정의 함수를 적용하려면 map() 메소드를 사용한다.
    • 사용자 정의 함수에는 단일 값을 입력하고 반환한다.
  • apply() 메소드는 데이터프레임시리즈에 모두 적용할 수 있다.
  • apply() 메소드는 요소별로 함수를 적용한다.
  • applymap()apply() 메소드는 호출할 수 있는 사용자 정의 함수만 인수로 가질 수 있다.
  • map() 메소드는 딕셔너리, 시리즈, 사용자 정의 함수를 인자로 가질 수 있다.
예제 : 데이터프레임에 람다 함수를 인수로 갖는 applymap() 메소드 적용하기
df = pd.DataFrame([[1, 2.12], [3.356, 4.567]])
df
df.applymap(lambda x: len(str(x)))

 

  • 다음과 같이 df에 람다 함수를 적용하거나 제곱 연산을 수행할 수 있다.
df.applymap(lambda x: x**2)
df ** 2

 

  • 인수가 딕셔너리형일 때, 딕셔너리 내에 키로써 존재하지 않는 시리즈 값들은 NaN으로 변환된다.
>>> ser = pd.Series(['cat', 'dog', np.nan, 'rabbit'])     # ser 객체 생성
>>> ser
0       cat
1       dog
2       NaN
3    rabbit
dtype: object

 

  • map() 메소드에는 딕셔너리, 시리즈, 사용자 정의 함수를 사용할 수 있다.
    • 딕셔너리에 존재하지 않는 값들은 NaN으로 변환된다.
>>> ser.map({'cat': 'kitten', 'dog': 'puppy'})
0    kitten
1     puppy
2       NaN
3       NaN
dtype: object

 

  • map() 메소드에 사용자 정의 함수를 인수로 사용할 수 있다.
>>> ser.map('I am a {}'.format)
0       I am a cat
1       I am a dog
2       I am a nan
3    I am a rabbit
dtype: object

 

  • 손실 값에 함수를 적용하지 않고 NaN 값을 유지하려면 다음과 같이 na_action='ignore'을 입력한다.
>>> ser.map('I am a {}'.format, na_action='ignore')
0       I am a cat
1       I am a dog
2              NaN
3    I am a rabbit
dtype: object

 

728x90
그리드형(광고전용)

'In-depth Study > Pandas' 카테고리의 다른 글

[Pandas] 수학 계산  (0) 2022.05.31
[Pandas] 데이터의 그룹 연산  (0) 2022.05.30
[Pandas] 데이터 가공  (0) 2022.05.29
[Pandas] 데이터 타입과 입출력  (0) 2022.05.27
[Pandas] 데이터 처리  (0) 2022.05.27
[Pandas] 판다스 데이터 구조  (1) 2022.05.24
[Pandas] 판다스(Pandas) 개요  (0) 2022.05.24
⚠️AdBlock이 감지되었습니다. 원할한 페이지 표시를 위해 AdBlock을 꺼주세요.⚠️
starrykss
starrykss
별의 공부 블로그 🧑🏻‍💻


📖 Contents 📖