2025-04-08

장상희·2025년 4월 8일

파이썬

목록 보기
10/31

반올림 (round)

round 함수는 DataFrame 객체 내의 요소를 반올림하는 메서드입니다.

df.round(decimals=0, args, kwargs) decimals : 소수 n번째 자리 '까지' 반올림을 합니다. 만약 음수면 10의 n승 자리 까지 반올림 합니다.

col = ['col1','col2','col3']
row = ['row1','row2','row3']
data = np.random.rand(3,3)*100
df = pd.DataFrame(data=data, index=row, columns=col)
print(df)

#col1       col2       col3
#row1  32.483428  78.515393  84.493119
#row2  50.778151  47.112292  92.796244
#row3   0.004339  64.110418  89.857246

합계 (sum), 곱 (prod, product)

sum 메서드는 객체의 행이나 열의 총 합계를 구하는 메서드 입니다.

prod 메서드는 객체의 행이나 열의 곱을 구하는 메서드 입니다.

product메서드와 동일합니다.

객체 생성

col = ['col1','col2','col3']
row = ['row1','row2','row3']
data = [[1,2,3],[4,5,6],[7,np.nan,9]]
df = pd.DataFrame(data=data,index=row,columns=col)
print(df)

#      col1  col2  col3
#row1     1   2.0     3
#row2     4   5.0     6
#row3     7   NaN     9

열의 합

print(df.sum(axis=0))#열의 합

#col1    12.0
#col2     7.0
#col3    18.0
#dtype: float64

행의 합

print(df.sum(axis=1))#행의 합

#row1     6.0
#row2    15.0
#row3    16.0
#dtype: float64

위 계산에서는 NaN을 무시하고 계산한 것을 알 수 있습니다.

skipna=False일 경우 NaN이 포함되는경우에는 NaN을 반환합니다.

col = ['col1','col2','col3']
row = ['row1','row2','row3']
data = [[1,2,3],[4,5,6],[7,np.nan,9]]
df = pd.DataFrame(data=data,index=row,columns=col)

print(df.sum(axis=0,skipna=False))

#col1    12.0
#col2     NaN
#col3    18.0
#dtype: float64

min_count를 변경하여 계산하기

min_count는 계산에 필요한 숫자의 최소 갯수를 의미합니다.
즉, min_count=3이라면 NaN을 포함하는 행의 경우 숫자가 2개이기 때문에
skipna=True임에도 NaN을 출력하게 됩니다.

print(df.sum(axis=1,min_count=3))#min_count는 계산에 필요한 최고 샛수를 의미한다

#row1     6.0
#row2    15.0
#row3     NaN
#dtype: float64

절대값 (abs)

abs메서드는 각 요소의 절댓값을 반환하는 메서드입니다.

col = ['col1','col2','col3']
row = ['row1','row2','row3']
data = [[-1,2,-3.5],[4,-5.5, 3+4j],[7,np.nan,0]]
df = pd.DataFrame(data=data,index=row,columns=col)
print(df)

#      col1  col2      col3
#row1    -1   2.0 -3.5+0.0j
#row2     4  -5.5  3.0+4.0j
#row3     7   NaN  0.0+0.0j
col = ['col1','col2','col3']
row = ['row1','row2','row3']
data = [[-1,2,-3.5],[4,-5.5, 3+4j],[7,np.nan,0]]
df = pd.DataFrame(data=data,index=row,columns=col)
print(df.abs( ))

#      col1  col2  col3
#row1     1   2.0   3.5
#row2     4   5.5   5.0
#row3     7   NaN   0.0

전치 (transpose, T)

transpose 메서드는 Dataframe객체를 전치 하는 메서드입니다.

만약 (n,m)짜리 DataFrame이라면 (0,0) 부터 (n,m)을 연결하는 대각선을 중심으로 뒤집는것과 같습니다.

※ T 메서드는 transpose 메서드와 동일합니다.

df.transpose(args, copy=False)

copy: 사본을 반환할지 여부입니다. 여러 dtype으로 이루어진 경우 자동으로 True가 됩니다.

col = ['col1','col2','col3']
row = ['row1','row2','row3','row4']
data = [['A',1,2],['B',3,4],['C',5,6],['D',7,8]]
df = pd.DataFrame(data=data,index=row,columns=col)
print(df)

#     col1  col2  col3
#row1    A     1     2
#row2    B     3     4
#row3    C     5     6
#row4    D     7     8
print(df.transpose())#행,열을 뒤집음
#     row1 row2 row3 row4
#col1    A    B    C    D
#col2    1    3    5    7
#col3    2    4    6    8

순위 (rank)

rank 메서드는 축에 대해서 순위를 매기는 메서드 입니다. 동일 순위일 경우 평균을 반환합니다.

기본 사용법

df.rank(axis=0, method='average', numeric_only=None, na_option='keep', ascending=True, pct=False)

axis

: {0 : index / 1 : columns} 순위를 매길 레이블입니다.

method

: {'average' / 'min' / 'max' / 'first' / 'dense'} 동순위 일때 처리 방법입니다.

average는 평균, min은 낮은순위, max는 높은순위, first는 나타나는순서대로

dense의 경우는 min과 같지만 그룹간 순위는 항상 1씩 증가합니다

.

method에 따른 차이

method에따라 동점의 경우 순위가 어떻게 매겨지는지 확인 할 수 있습니다.

average : D와 I의 경우 각각 3등 4등이기때문에 3.5 출력

min : A, B, F의 경우 각각 5등 6등 7등으로 가장 낮은등수인 5 출력

max : A, B, F의 경우 각각 5등 6등 7등으로 가장 높등수인 7 출력

first : 동점일경우 위에서부터 매김 D와 I 각각 3등 4등

dense : min처럼 동작하지만 등수가 순차적으로 증가

numeric_only

: {True / False} 숫자만 순위를 매길지 여부 입니다.

na_option

: {'keep' / 'top' / 'bottom'} NaN값의 처리 방법입니다.

keep의 경우 NaN순위 할당, top의 경우 낮은순위 할당, bottom의 경우 높은 순위를 할당합니다.

na_option에 따른 차이

na_option에 따라 Na가 포함된경우 순위가 어떻게 매겨지는지 확인할 수 있습니다.

추가로 pct 의 경우도 추가하였습니다.

keep : Na요소에 NaN을 부여하여 그대로 둡니다.

top : Na에게 가장 높은 순위를 부여합니다. 1등이 된것을 볼 수 있습니다.

bottom : Na에게 가장 높은 순위를 부여합니다. 9등이 된것을 볼 수 있습니다.

pct : True일 경우 백분위수로 표시합니다.

ascending

: {True / False} 오름차순으로 할지의 여부 입니다.

pct

: {True / False} 순위를 백분위수형식으로 할지 여부입니다.

객체 생성

data = [[5],[5],[pd.NA],[3],[-3.1],[5],[0.4],[6.7],[3]]
row = ['A★','B★','C','D☆','E','F★','G','H','I☆']
df = pd.DataFrame(data=data, index=row, columns=['Value'])
print(df)

#   Value
#A★     5
#B★     5
#C   <NA>
#D☆     3
#E   -3.1
#F★     5
#G    0.4
#H    6.7
#I☆     3
  
df['average']=df['Value'].rank(method='average')#데이터에서 평균을 구하고
df['min']=df['Value'].rank(method='min')#데이터에서 최소값 반환
df['max']=df['Value'].rank(method='max')#최고값 반환
df['first']=df['Value'].rank(method='first')#동점일경우 위에서부터 매김 D와 I 각각 3등 4등
df['dense']=df['Value'].rank(method='dense')#min처럼 동작하지만 등수가 순차적으로 증가
print(df)

#   Value  average  min  max  first  dense
#A★     5      6.0  5.0  7.0    5.0    4.0
#B★     5      6.0  5.0  7.0    6.0    4.0
#C   <NA>      NaN  NaN  NaN    NaN    NaN
#D☆     3      3.5  3.0  4.0    3.0    3.0
#E   -3.1      1.0  1.0  1.0    1.0    1.0
#F★     5      6.0  5.0  7.0    7.0    4.0
#G    0.4      2.0  2.0  2.0    2.0    2.0
#H    6.7      8.0  8.0  8.0    8.0    5.0
#I☆     3      3.5  3.0  4.0    4.0    3.0
df['keep']=df['Value'].rank(na_option='keep')#Na요소에 NaN을 부여하여 그대로 둡니다.
df['top']=df['Value'].rank(na_option='top')#Na에게 가장 높은 순위를 부여합니다. 1등이 된것을 볼 수 있습니다.
df['bottom']=df['Value'].rank(na_option='bottom')#Na에게 가장 높은 순위를 부여합니다. 9등이 된것을 볼 수 있습니다.
df['pct']=df['Value'].rank(pct=True)#True일 경우 백분위수로 표시합니다.

print(df)

#   Value  average  min  max  first  dense  keep  top  bottom     pct
#A★     5      6.0  5.0  7.0    5.0    4.0   6.0  7.0     6.0  0.7500
#B★     5      6.0  5.0  7.0    6.0    4.0   6.0  7.0     6.0  0.7500
#C   <NA>      NaN  NaN  NaN    NaN    NaN   NaN  1.0     9.0     NaN
#D☆     3      3.5  3.0  4.0    3.0    3.0   3.5  4.5     3.5  0.4375
#E   -3.1      1.0  1.0  1.0    1.0    1.0   1.0  2.0     1.0  0.1250
#F★     5      6.0  5.0  7.0    7.0    4.0   6.0  7.0     6.0  0.7500
#G    0.4      2.0  2.0  2.0    2.0    2.0   2.0  3.0     2.0  0.2500
#H    6.7      8.0  8.0  8.0    8.0    5.0   8.0  9.0     8.0  1.0000
#I☆     3      3.5  3.0  4.0    4.0    3.0   3.5  4.5     3.5  0.4375

차이이산

diff는 한 객체 내에서 열과 열 / 행과 행의 차이를 출력하는 메서드 입니다.

axis : 비교할 축을 지정합니다. axis=0 인 경우 행끼리 비교하고 axis=1인 경우 열 끼리 비교합니다.
periods : 비교할 간격을 지정합니다. 기본은 +1로 바로 이전 값과 비교합니다.

a = [1,2,3,4,5,6,7,8]
b = [1,2,4,8,16,32,64,128]
c = [8,7,6,5,4,3,2,1]
data = {"col1":a,"col2":b,"col3":c}
df = pd.DataFrame(data)
print(df)

#   col1  col2  col3
#0     1     1     8
#1     2     2     7
#2     3     4     6
#3     4     8     5
#4     5    16     4
#5     6    32     3
#6     7    64     2
#7     8   128     1

axis에 따라서 행끼리 비교할지, 열 끼리 비교할지 정할 수 있습니다.

axis 인 경우 행 - 바로전 행 의 값을 출력합니다. 비교할 값이 없다면 NaN을 출력합니다.

print(df.diff(axis=0))

#   col1  col2  col3
#0   NaN   NaN   NaN
#1   1.0   1.0  -1.0
#2   1.0   2.0  -1.0
#3   1.0   4.0  -1.0
#4   1.0   8.0  -1.0
#5   1.0  16.0  -1.0
#6   1.0  32.0  -1.0
#7   1.0  64.0  -1.0

차이백분률

pct_change는 한 객체 내에서 행과 행의 차이를 현재값과의 백분율로 출력하는 메서드 입니다.즉, (다음행 - 현재행)÷현재행 을 의미합니다.

※ 자세한 내용을 아래 예시를 참고 바랍니다.

df.pct_change(periods=1, fill_method='pad', limit=None, freq=None, kwargs)

periods : 비교할 간격을 지정합니다. 기본은 +1로 바로 이전 값과 비교합니다.

fill_method : {ffill : 앞의 값으로 채움 / bfill : 뒤의 값으로 채움} 결측치를 대체할 값입니다.

limit : 결측값을 몇개나 대체할지 정할 수 있습니다.

freq : 시계열 API에서 사용할 증분을 지정합니다. (예: 'M' 또는 BDay( ))

a = [1,1,4,4,1,1]
b = [1,2,4,8,16,32]
c = [1,np.nan,np.nan,np.nan,16,64]
data = {"col1":a,"col2":b,"col3":c}
df = pd.DataFrame(data)
print(df)

#   col1  col2  col3
#0     1     1   1.0
#1     1     2   NaN
#2     4     4   NaN
#3     4     8   NaN
#4     1    16  16.0
#5     1    32  64.0

fill_method / limit인수의 사용

fill_method인수는 결측치를 대체할 값을 지정할 수 있습니다.
fill_method='ffill'인 경우는 기본값으로 바로 윗값으로 결측치를 대체합니다.
fill_method='bfill'인 경우는 바로 아랫값으로 결측치를 대체합니다.

print(df.pct_change(fill_method='bfill'))

#   col1  col2  col3
#0   NaN   NaN   NaN
#1  0.00   1.0  15.0 
#2  3.00   1.0   0.0
#3  0.00   1.0   0.0 # col3의 경우 바로 아랫값인수로 결측치를 채우기때문에 16으로 채워집니다.
#4 -0.75   1.0   0.0 # 때문에 (16-16)/16 해서 0입니다.
#5  0.00   1.0   3.0

limit인수는 결측치를 몇개까지 대체할지 지정합니다.

print(df.pct_change(limit=2))

#   col1  col2  col3
#0   NaN   NaN   NaN
#1  0.00   1.0   0.0 
#2  3.00   1.0   0.0 # 2번째 결측치까지는 'ffill'에따라 1로 채워집니다. 
#3  0.00   1.0   NaN # 3번째 결측치는 limit=2이므로 NaN 그대로 둡니다.
#4 -0.75   1.0   NaN 
#5  0.00   1.0   3.0

누적 계산 (expending)

expanding 메서드는 행이나 열의 값에 대해 누적으로 연산을 수행하는 메서드입니다.
df.expanding( ).sum( ) 처럼 추가 메서드를 이용하여 연산을 수행합니다

기본적으로 df.expanding( ).추가연산메서드 형태로 지정하면, 해당 연산을 누적으로 진행하게 됩니다.

print(df.expanding().sum())

#      col1  col2
#row1   1.0   3.0 
#row2   3.0  10.0
#row3   6.0  15.0
#row4  10.0  21.0 #열마다 누적으로 sum을 진행

min_period를 지정하게되면, 입력값 만큼의 갯수가 충족되지 않으면 연산을 하지 않고 NaN을 반환합니다.

print(df.expanding(min_periods=4).sum())

#      col1  col2
#row1   NaN   NaN
#row2   NaN   NaN
#row3   NaN   NaN
#row4  10.0  21.0

axis=1로 지정하면 열 기준으로 누적값의 계산이 수행됩니다.
/

print(df.expanding(axis=1).sum())

#      col1  col2
#row1   1.0   4.0
#row2   2.0   9.0
#row3   3.0   8.0
	#row4   4.0  10.0

method='table'로 입력할 경우 numba 라이브러리를 이용해 연산을 테이블단위로 롤링할 수 있습니다.
추가 연산 메서드에 인수로 engine='numba'를 지정해주어야 합니다.(engine=’numba’를 지정해주면 더 빨라진다)

print(df.expanding(method='table').sum(engine='numba'))

#      col1  col2
#row1   1.0   3.0 # 연산의 결과는 singe때와 동일하지만 대량의 데이터 연산에는 빠른 속도를 지원함.
#row2   3.0  10.0
#row3   6.0  15.0
#row4  10.0  21.0

기간이동 계산 (rolling)

df.rolling(window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None, method='single')

window

: 계산할 창(window)의 크기 입니다. 열 기준으로 계산할 경우 행의 수입니다.

min_periods

: 계산할 최소 크기(기간) 입니다.

window

안의 값의 수가

min_periods

의 값보다 작을경우

NaN

을 출력합니다.

기본적으로 window 크기와 동일합니다.

center

: {True / False} 레이블을 window의 중간에 둘지 여부입니다. 기본값은 False로 레이블이 창 우측에 위치합니다.

win_type

: {'triang' / 'gaussian' / ...} 가중치를 넣어 계산할 경우 계산 방식 입니다. 때에따라 연산 메서드에 추가 인수를 지정해야할수도 있습니다.

on

: 시계열 인덱스나, 시계열과 유사한 열이 있을 경우 이 열을 기준으로

rolling

을 수행할 수 있습니다.

axis

: 계산의 기준이 될 축입니다.

closed

: {'left' / 'right' / 'both' / 'neither'} window가 닫히는 방향입니다. 자세한건 아래 예시 참고바랍니다

method

:{'single' / 'table'}

numba

를 이용하여 테이블 계산을 진행하여 속도를 높힐지 여부입니다. 현재 'single'만 사용가능합니다.

먼저 기본적인 사용법 예시를위하여 6x2 짜리 데이터를 만들어 보겠습니다.

period = pd.period_range(start='2022-01-13 00:00:00',end='2022-01-13 02:30:00',freq='30T')
data = {'col1':[1,2,3,4,5,6],'col2':period}
idx = ['row1','row2','row3','row4','row5','row6']
df = pd.DataFrame(data= data, index = idx)
print(df)
df.dtypes

#      col1              col2
#row1     1  2022-01-13 00:00
#row2     2  2022-01-13 00:30
#row3     3  2022-01-13 01:00
#row4     4  2022-01-13 01:30
#row5     5  2022-01-13 02:00
#row6     6  2022-01-13 02:30
#<ipython-input-36-a5e63c3b01c2>:1: FutureWarning: 'T' is deprecated and will be removed in a future version, please use 'min' instead.
#  period = pd.period_range(start='2022-01-13 00:00:00',end='2022-01-13 02:30:00',freq='30T')

window 크기를 지정해주면, 현재 행 이전으로 window 크기 만큼의 계산을 수행합니다.

print(df['col1'].rolling(window=3).sum()) # 뒤에 추가 메서드를 이용하여 연산을 지정해주어야합니다.

#row1     NaN
#row2     NaN
#row3     6.0
#row4     9.0
#row5    12.0
#row6    15.0
#Name: col1, dtype: float64

on 인수의 사용

on='col2'를 이용하여 col2열의 시계열 인덱스를 기준으로 rolling의 수행이 가능합니다.

print(df.rolling(window='60T',on='col2').sum())

#      col1              col2
#row1   1.0  2022-01-13 00:00
#row2   3.0  2022-01-13 00:30
#row3   5.0  2022-01-13 01:00
#row4   7.0  2022-01-13 01:30
#row5   9.0  2022-01-13 02:00
#row6  11.0  2022-01-13 02:30
#<ipython-input-38-f99784476314>:1: FutureWarning: 'T' is deprecated and will be removed in a future version, please use 'min' instead.
#  print(df.rolling(window='60T',on='col2').sum())

그룹화 계산 (groupby)

groupby 메서드는 데이터를 그룹화하여 연산을 수행하는 메서드 입니다.

df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=NoDefault.no_default, observed=False, dropna=True)

by

: 그룹화할 내용입니다. 함수, 축, 리스트 등등이 올 수 있습니다.

axis

: 그룹화를 적용할 축입니다.

level

: 멀티 인덱스의 경우 레벨을 지정할 수 있습니다.

as_index

: 그룹화할 내용을 인덱스로 할지 여부입니다. False이면 기존 인덱스가 유지됩니다.

sort

: 그룹키를 정렬할지 여부입니다.

group_keys

: apply메서드 사용시 결과에따라 그룹화 대상인 열이 인덱스와 중복(group key)이 될 수 있습니다. 이 때,

group_keys=False

로 인덱스를 기본값으로 지정할 수 있습니다.

squeeze

: 결과가 1행 or 1열짜리 데이터일 경우 Series로, 1행&1열 짜리 데이터일 경우 스칼라로 출력합니다.

observed

: Categorical로 그룹화 할 경우 Categorical 그룹퍼에 의해 관찰된 값만 표시할 지 여부입니다.

dropna

: 결측값을 계산에서 제외할지 여부입니다.

idx=['A','A','B','B','B','C','C','C','D','D','D','D','E','E','E']
col=['col1','col2','col3']
data = np.random.randint(0,9,(15,3))
df = pd.DataFrame(data=data, index=idx, columns=col).reset_index()
print(df)

#   index  col1  col2  col3
#0      A     8     2     8
#1      A     6     7     6
#2      B     6     0     7
#3      B     4     8     2
#4      B     8     3     1
#5      C     1     3     6
#6      C     7     5     2
#7      C     4     7     8
#8      D     6     5     2
#9      D     4     5     3
#10     D     4     8     0
#11     D     3     1     3
#12     E     6     2     7
#13     E     5     5     5
#14     E     1     6     3

추가 메서드 없이 groupby 메서드를 실행하면 DataFrameGroupBy 오브젝트가 생성이 됩니다.

print(df.groupby('index')) # index 컬럼에 대해서 groupby 수행

여기에 추가 연산 메서드를 입력하면, 해당 열의 그룹화된 데이터에 대해서 연산이 수행됩니다.

print(df.groupby('index').mean())

#           col1      col2      col3
#index                              
#A      3.500000  3.000000  4.500000
#B      1.666667  3.000000  5.666667
#C      3.333333  3.000000  4.666667
#D      3.250000  4.000000  4.750000
#E      0.666667  6.333333  4.333333

agg메서드를 이용해 여러 연산을 수행할 경우 MultiColumns 형태로 출력됩니다.

print(df.groupby('index').agg(['sum','mean']))

#      col1       col2           col3          
#       sum  mean  sum      mean  sum      mean
#index                                         
#A       14  7.00    9  4.500000   14  7.000000
#B       18  6.00   11  3.666667   10  3.333333
#C       12  4.00   15  5.000000   16  5.333333
#D       17  4.25   19  4.750000    8  2.000000
#E       12  4.00   13  4.333333   15  5.000000

observed 인수의 사용

Categorical 객체를 생성할 때, 그룹화(groupby)할 열에 있는 값이 아닌 값을 포함하게되면, 그룹화 할 때 해당 값을 표시할지여부를 선택할 수 있습니다.

df_cat = pd.Categorical(df['index'], categories=['A','B','C','D','E','F']) # df의 index열에 대해서 A,B,C,D,E,F 로 Categorical을 하여 df_cat 생성
print(df_cat)

#['A', 'A', 'B', 'B', 'B', ..., 'D', 'D', 'E', 'E', 'E']
#Length: 15
#Categories (6, object): ['A', 'B', 'C', 'D', 'E', 'F']

위 catrory 객체에 대해서 col1열을 groupby 하면 아래와 같이 카테고리에만 존재하는 F에대한 groupby 값이 출력됩니다

print(df['col1'].groupby(df_cat).count())

#A    2
#B    3
#C    3
#D    4
#E    3
#F    0
#Name: col1, dtype: int64
#<ipython-input-47-614f52aaf8fe>:1: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
#  print(df['col1'].groupby(df_cat).count())

observed=True로 할경우 관찰되지 않는값 (카테고리에만 존재하는값)은 표시되지 않습니다.

print(df['col1'].groupby(df_cat,observed=True).count())

#A    2
#B    3
#C    3
#D    4
#E    3
#Name: col1, dtype: int64

level인수의 사용 (Multi Index)

Multi Index의 경우

level을 숫자나 str 형태로 지정해주어

groupby를 실행할 수 있습니다.

먼저 Multi Index 객체를 생성해보겠습니다.

idx = [['idx1','idx1','idx2','idx2','idx2'],['row1','row2','row1','row2','row3']]
col = ['col1','col2','col2']
data = np.random.randint(0,9,(5,3))
df = pd.DataFrame(data=data, index = idx, columns = col).rename_axis(index=['lv0','lv1'])#인덱스의 이름을 레벨0과 레벨1로 재설정한다
print(df)

#           col1  col2  col2
#lv0  lv1                   
#idx1 row1     4     5     3
#     row2     0     7     4
#idx2 row1     4     6     7
#     row2     6     4     5
#     row3     1     4     7

level을 int로 지정해주는 경우

print(df.groupby(level=1).sum())

#      col1  col2  col2
#lv1                   
#row1     8    11    10
#row2     6    11     9
#row3     1     4     7

level을 str로 지정해주는경우 + (여러개 지정시 순차적으로 groupby 됩니다.)

print(df.groupby(['lv1','lv0']).sum())

#           col1  col2  col2
#lv1  lv0                   
#row1 idx1     4     5     3
#     idx2     4     6     7
#row2 idx1     0     7     4
#     idx2     6     4     5
#row3 idx2     1     4     7

지수가중함수 (ewm)

ewm 은 지수가중함수 입니다. 지수가중함수는 오래된 데이터에 지수감쇠를 적용하여 최근 데이터가 더 큰 영향을 끼지도록 가중치를 주는 함수입니다.
보통 추가 메서드로 mean() 을 사용해서 지수가중평균으로 사용합니다.

df.ewm(com=None, span=None, halflife=None, alpha=None, min_periods=0, adjust=True, ignore_na=False, axis=0, times=None, method='single')

기본적으로 가중치를 결정하는 요소는 alpha 로 표기되는 평활계수(감쇠계수) 입니다. com / span / halflife를 통해 자동 계산하도록 하거나, alpha를 통해 직접 설정할 수 있습니다.

com : 질량중심 값으로 평활계수를 계산합니다. [ a = 1(1+com) ]

span : 계산 기간으로 평활계수를 계산합니다. [ a = 2/(span+1) ]

halflife : 반감기를 이용하여 평활계수를 계산합니다. [ a= e^(-ln(2) / halflife) ]

alpha : 평활계수를 직접 입력합니다. [ 0 < a ≤ 1 ]

min_periods : 계산을위한 최소 기간입니다.

adjust : 상대적 가중치의 불균형을 해소하기위해 조정계수로 나눌지의 여부입니다. 대체로 값이 많을수록 adjust를 하는것이 유리합니다.

ignore_na : 가중치를 계산할때 누락값을 무시할지 여부 입니다.

[x0, None, x1] 일때, 인 경우 ignore_na = False 이면 절대위치를 기반으로 하며,

x0와 x2의 가중치는 adjust = [ True인경우 (1-a)^2와 1 / False인 경우 (1-a)^2와 a ] 입니다.

[x0, None, x1] 일때, 인 경우 ignore_na = False 이면 절대위치를 기반으로 하며,

x0와 x2의 가중치는 adjust = [ True인경우 (1-a)와 1 / False인 경우 (1-a)와 a ] 입니다.

axis : 계산을 수행할 축 입니다.

times : 관찰에 해당하는 시간입니다. 단조증가 형태의 datetime64[ns] 형태여야합니다.

method : {single / table} 한 줄씩 계산할지(기본값) 아니면 numba engine을 사용해서 table단위로 계산할지 정할 수 있습니다.

numba 라이브러리를 import 해야하며 사용시 ewm(method='table').mean(engine='numba') 처럼 추가 메서드에 engine 설정을 해줘야합니다.

예시

data = {'val':[1,4,2,3,2,5,13,10,12,14,np.nan,16,12,20,22]}
df = pd.DataFrame(data).reset_index()
print(df)
# index   val
#0       0   1.0
#1       1   4.0
#2       2   2.0
#3       3   3.0
#4       4   2.0
#5       5   5.0
#6       6  13.0
#7       7  10.0
#8       8  12.0
#9       9  14.0
#10     10   NaN
#11     11  16.0
#12     12  12.0
#13     13  20.0
#14     14  22.0

기본적인 사용법

기본적으로는

com / span / halflife

를 통한 평활계수의 계산, 또는

alpha

를 통해 평활계수를 직접 입력하여 지수가중평균을 표현합니다.

지수가중평균 출력하기

df2 = df.assign(ewm=df['val'].ewm(alpha=0.3).mean()) # val열에 ewm 메서드적용 후 df에 추가
ax = df.plot(kind='bar',x='index',y='val') # ax에 df의 bar chart 생성
ax2= df2.plot(kind='line',x='index', y='ewm', color='red', ax=ax) # ax2에 df2의 line chart 생성후 ax에 추가
plt.show()
#파란색 막대가 지수
#붉은 선은 지수가중평균

image.png

alpha에 따른 차이

alpha

는 평활계수로써, 자동 계산이 가능하지만,

alpha

인수를 직접 입력하여 설정이 가능합니다.

alpha가 클수록 더 큰 변화에 민감하며, alpha가 작을수록 평활한 그래프가 생성됩니다

df2 = df.assign(ewm_a_low=df['val'].ewm(alpha=0.1).mean()) #alpha=0.1로 df2 생성
df3 = df.assign(ewm_a_high=df['val'].ewm(alpha=0.7).mean()) #alpha=0.7로 df3 생성
ax = df.plot(kind='bar',x='index',y='val') 
ax2= df2.plot(kind='line',x='index', y='ewm_a_low', color='red', ax=ax) # alpha=0.1 은 적색
ax3= df3.plot(kind='line',x='index', y='ewm_a_high', color='green', ax=ax) # alpha=0.7 은 녹색
plt.show()

image.png

alpha가 0.1인 적색선보다. alpha가 0.7인 녹색선이 급격한 변화에 더 민감한 것을 볼 수 있습니다.

span 인수의 사용

span은 기간을 지정하여 평활계수를 계산하는 인수입니다. 계산식은 a = 2/(span+1)으로 계산 기간이 길어질수록 a가 작아집니다

df2 = df.assign(span_4=df['val'].ewm(span=4).mean())
df3 = df.assign(span_8=df['val'].ewm(span=8).mean())
ax = df.plot(kind='bar',x='index',y='val')
ax2= df2.plot(kind='line',x='index', y='span_4', color='red', ax=ax)
ax3= df3.plot(kind='line',x='index', y='span_8', color='green', ax=ax)
plt.show()

image.png

span이 긴 녹색이 span이 짧은 적색선보다 덜 민감하게 반응하는 것을 확인 할 수 있습니다.
span이 길면 그만큼 과거의 데이터의 영향이 커지기 때문입니다.

com 인수의 사용
com 은 질량중심 감쇠법으로 평활계수를 계산하는 인수입니다. 계산식은 a=1/(1+com)으로 com이 커질수록 a가 작아집니다.

image.png

com이 큰 녹색이 com이 작은 적색보다 덜 민감하게 반응하는 것을 확인할 수 있습니다.
com이 큰 녹색이 com이 작은 적색보다 덜 민감하게 반응하는 것을 확인할 수 있습니다.

halflife 인수의 사용
halflife인수는 반감기를 이용하여 평활계수를 계산하는 인수입니다. 계산식은 a=1-e^(-ln(2)/halflife) 으로 halflife가 길어질수록 a가 작아집니다.

image.png

halflife 반감기가 길수록(녹색) 더욱 둔감한 그래프가 그려지는것을 확인할 수 있습니다.

adjust인수의 사용

상대적 가중치의 불균형을 해소하기위해 조정계수로 나눌지의 여부입니다. 대체로 값이 많을수록 adjust를 하는것이 유리합니다.

df2 = df.assign(adj_True=df['val'].ewm(alpha=0.2,adjust=True).mean())
df3 = df.assign(adj_False=df['val'].ewm(alpha=0.2,adjust=False).mean())
ax = df.plot(kind='bar',x='index',y='val')
ax2= df2.plot(kind='line',x='index', y='adj_True', color='red', ax=ax)
ax3= df3.plot(kind='line',x='index', y='adj_False', color='green', ax=ax)
plt.show()

image.png

ignore_na인수의 사용

ignore_na는 결측치가 존재할 경우 가중치를 어떻게 설정할지 정하는 인수 입니다.

[x0, None, x1] 일때, 인 경우 ignore_na = False 이면 절대위치를 기반으로 하며,

x0와 x2의 가중치는 adjust = [ True인경우 (1-a)^2와 1 / False인 경우 (1-a)^2와 a ] 입니다.

[x0, None, x1] 일때, 인 경우 ignore_na = False 이면 절대위치를 기반으로 하며,

x0와 x2의 가중치는 adjust = [ True인경우 (1-a)와 1 / False인 경우 (1-a)와 a ] 입니다.

df2 = df.assign(ignore_na_True=df['val'].ewm(alpha=0.2,ignore_na=True).mean())
df3 = df.assign(ignore_na_False=df['val'].ewm(alpha=0.2,ignore_na=False).mean())
ax = df.plot(kind='bar',x='index',y='val')
ax2= df2.plot(kind='line',x='index', y='ignore_na_True', color='red', ax=ax)
ax3= df3.plot(kind='line',x='index', y='ignore_na_False', color='green', ax=ax)
plt.show()

image.png

결측치가 있는 10번 data부터 ignore_na의 여부에 따라 그래프가 달라지는것을 볼 수 있습니다.

method 인수의 사용

method인수는 single인 경우 한줄씩, table인 경우 전체 테이블을 한번에 계산합니다. 데이터가 많을수록 method='table'이 속도에서 유리합니다.

사용시 추가 메서드에서 engine='numba' 형태로 설정을 해주어야 합니다.

import numba
print(df['val'].ewm(alpha=0.2, method='table').mean(engine='numba'))
profile
프로그래머 꿈나무

0개의 댓글