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메서드와 동일합니다.
객체 생성
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메서드는 각 요소의 절댓값을 반환하는 메서드입니다.
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 메서드는 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 메서드는 축에 대해서 순위를 매기는 메서드 입니다. 동일 순위일 경우 평균을 반환합니다.
기본 사용법
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인수는 결측치를 대체할 값을 지정할 수 있습니다.
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
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
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 메서드는 데이터를 그룹화하여 연산을 수행하는 메서드 입니다.
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 은 지수가중함수 입니다. 지수가중함수는 오래된 데이터에 지수감쇠를 적용하여 최근 데이터가 더 큰 영향을 끼지도록 가중치를 주는 함수입니다.
보통 추가 메서드로 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()
#파란색 막대가 지수
#붉은 선은 지수가중평균
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()
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()
span이 긴 녹색이 span이 짧은 적색선보다 덜 민감하게 반응하는 것을 확인 할 수 있습니다.
span이 길면 그만큼 과거의 데이터의 영향이 커지기 때문입니다.
com 인수의 사용
com 은 질량중심 감쇠법으로 평활계수를 계산하는 인수입니다. 계산식은 a=1/(1+com)으로 com이 커질수록 a가 작아집니다.
com이 큰 녹색이 com이 작은 적색보다 덜 민감하게 반응하는 것을 확인할 수 있습니다.
com이 큰 녹색이 com이 작은 적색보다 덜 민감하게 반응하는 것을 확인할 수 있습니다.
halflife 인수의 사용
halflife인수는 반감기를 이용하여 평활계수를 계산하는 인수입니다. 계산식은 a=1-e^(-ln(2)/halflife) 으로 halflife가 길어질수록 a가 작아집니다.
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()
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()
결측치가 있는 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'))