생각하는 이상훈 2023. 8. 21. 19:45
728x90

나머지 객체간 연산

 

곱셈(mul, rmul), 나눗셈(div, rdiv), 나머지(mod, rmod), 거듭제곱(pow, rpow) 4개의 연산들도 마찬가지로 기본적인 파이썬 연산자와 거의 같지만 차별화되는 것은 fill_value 인수를 통해 계산 불가한 값을 채워 넣는다는 것이다.


행렬곱(dot)

행렬곱은 다음과 같이 사용된다.

DataFrame.dot(other)

선형대수학에서 배운 행렬곱과 같은 내용이다.

     col1 col2                col1 col2                  col1   col2
row1    A    B     x     row1    a    b     =     row1  Aa+bc  Ab+Bd
row2    C    D           row2    c    d           row2  Ca+Dc  Cb+Dd

간단한 2x2 짜리 DataFrame을 두개 만들어서 계산을 진행해보자.

col = ['col1','col2']
row = ['row1','row2']
data1 = [[1,2],[3,4]]
data2 = [[5,6],[7,8]]
df1 = pd.DataFrame(data=data1)
df2 = pd.DataFrame(data=data2)
print(df1)
>>
   0  1
0  1  2
1  3  4
-------------------------------------------------------------------------------
print(df2)
>>
   0  1
0  5  6
1  7  8
df3 = df1.dot(df2)
print(df3)
>>
    0   1
0  19  22
1  43  50

계산과정은 아래와 같이 진행된다.

   0  1          0  1                0        1           0   1
0  1  2   x   0  5  6   =   0  1*5+2*7  1*6+2*8   =   0  19  22
1  3  4       1  7  8       1  1*7+3*8  3*6+4*8       1  43  50

객체 내 연산

판다스 객체내 연산 함수인 round, sum, prod, abs, transpose, rank, diff, pct_package, expending, rolling, groupby, ewm에 대해서 알아보자.

round(): DataFrame 객체 내의 요소를 반올림하는 메서드이다.

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

prod(): 객체의 행이나 열의 곱을 구하는 메서드이다.

abs(): 각 요소의 절댓값을 반환하는 메서드이다.

transpose() or T: Dataframe객체를 전치 하는 메서드이다. 만약 (n,m)짜리 DataFrame이라면 (0,0) 부터 (n,m)을 연결하는 대각선을 중심으로 뒤집는것과 같다.

rank(): 축에 대해서 순위를 매기는 메서드이다. 동일 순위일 경우 평균을 반환한다. 

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

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

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

rolling(): 현재 열에 대하여 일정 크기의 창(window)를 이용하여 그 window안의 값을 추가 메서드를 통해 계산하는 메서드이다.

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

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


예시

round

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  35.441830  30.006442  88.754181
row2  42.949147  62.131260  54.709369
row3  88.695079  27.138069   7.224099

#decimals = 0인 경우 0은 기본값으로 일의자리 까지 반올림
print(df.round(0))
>>
      col1  col2  col3
row1  35.0  30.0  89.0
row2  43.0  62.0  55.0
row3  89.0  27.0   7.0

#decimals > 0인 경우 소수 n번째 자리 까지 반올림
print(df.round(2))
>>
       col1   col2   col3
row1  35.44  30.01  88.75
row2  42.95  62.13  54.71
row3  88.70  27.14   7.22

#decimals < 0인 경우 10의 n승 자리 까지 반올림
print(df.round(-1))
>>
      col1  col2  col3
row1  40.0  30.0  90.0
row2  40.0  60.0  50.0
row3  90.0  30.0  10.0

sum

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

#skipna=False일 경우 NaN이 포함되는경우에는 NaN을 반환
print(df.sum(axis=0,skipna=False))
>>
col1    12.0
col2     NaN
col3    18.0
dtype: float64

#min_count 설정
print(df.sum(axis=1,min_count=3))
>>
row1     6.0
row2    15.0
row3     NaN
dtype: float64

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

 

prod

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.prod(axis=0))
>>
col1     28.0
col2     10.0
col3    162.0
dtype: float64

#행 요소 곱
print(df.prod(axis=1))
>>
row1      6.0
row2    120.0
row3     63.0
dtype: float64

print(df.prod(axis=0, skipna=False))
>>
col1     28.0
col2      NaN
col3    162.0
dtype: float64

print(df.prod(axis=1, min_count=3))
>>
row1      6.0
row2    120.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

print(df.abs( ))
>>
      col1  col2  col3
row1     1   2.0   3.5
row2     4   5.5   5.0
row3     7   NaN   0.0

transpose

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

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

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처럼 동작하지만 등수가 순차적으로 증가

df['keep']=df['Value'].rank(na_option='keep')
df['top']=df['Value'].rank(na_option='top')
df['bottom']=df['Value'].rank(na_option='bottom')
df['pct']=df['Value'].rank(pct=True)
print(df)
>>
   Value  keep  top  bottom     pct
A★     5   6.0  7.0     6.0  0.7500
B★     5   6.0  7.0     6.0  0.7500
C    <NA>   NaN  1.0     9.0     NaN
D☆     3   3.5  4.5     3.5  0.4375
E    -3.1   1.0  2.0     1.0  0.1250
F★     5   6.0  7.0     6.0  0.7500
G     0.4   2.0  3.0     2.0  0.2500
H     6.7   8.0  9.0     8.0  1.0000
I☆     3   3.5  4.5     3.5  0.4375

keep : Na요소에 NaN을 부여하여 그대로 둔다.
top : Na에게 가장 높은 순위를 부여합니다. 1등이 된것을 볼 수 있다.
bottom : Na에게 가장 높은 순위를 부여합니다. 9등이 된것을 볼 수 있다.
pct : True일 경우 백분위수로 표시한다.

 

diff

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

print(df.diff(axis=0))
>>
   col1  col2  col3
0   NaN   NaN   NaN # 뺄 바로 전 행이 없으므로 NaN
1   1.0   1.0  -1.0 # 1행 - 0행
2   1.0   2.0  -1.0 # 2행 - 1행
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 # 7행 - 6행

print(df.diff(axis=1))
>>
   col1  col2  col3 # col1은 뺄 이전 열이 없으므로 NaN출력
0   NaN     0     7 # col2 의 값은 기존 data의 col2 - col1
1   NaN     0     5 # col3 의 값은 기존 data의 col3 - col2
2   NaN     1     2
3   NaN     4    -3
4   NaN    11   -12
5   NaN    26   -29
6   NaN    57   -62
7   NaN   120  -127

print(df.diff(periods=3))
>>
   col1   col2  col3
0   NaN    NaN   NaN #3칸 이전 값이 없으므로 NaN
1   NaN    NaN   NaN # ' '
2   NaN    NaN   NaN # ' '
3   3.0    7.0  -3.0 # 열3 - 열0의 값 출력
4   3.0   14.0  -3.0
5   3.0   28.0  -3.0
6   3.0   56.0  -3.0
7   3.0  112.0  -3.0 # 열7 - 열4의 값 출력

print(df.diff(periods=-2))
>>
   col1  col2  col3
0  -2.0  -3.0   2.0 #열0 - 열2의 값 (마이너스이므로 뒤의값으로 계산)
1  -2.0  -6.0   2.0
2  -2.0 -12.0   2.0
3  -2.0 -24.0   2.0
4  -2.0 -48.0   2.0
5  -2.0 -96.0   2.0 # 열5 - 열7의 값
6   NaN   NaN   NaN # 2칸 뒤의 값이 없으므로 NaN
7   NaN   NaN   NaN # ' '

pct

a = [1,1,4,4,1,1]
b = [1,2,4,8,16,32]
c = [1,N,N,N,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

print(df.pct_change())
>>
   col1  col2  col3
0   NaN   NaN   NaN # 첫행은 이전행이 없으므로 NaN출력
1  0.00   1.0   0.0 # col1의 경우 이전행과 값이 같으므로 (1-1)/1 = 0 출력
2  3.00   1.0   0.0 # col2의 경우 2배씩 커지므로 차이는 자기자신 즉 결과=1
3  0.00   1.0   0.0 # col3의 경우 결측치가 위의 값 기준으로 됨. (1-1)/1=0 출력
4 -0.75   1.0  15.0
5  0.00   1.0   3.0

print(df.pct_change(periods=2))
>>
   col1  col2  col3
0   NaN   NaN   NaN 
1   NaN   NaN   NaN # 0행, 1행은 2개전값이 없으므로 NaN 출력
2  3.00   3.0   0.0 # col1의 경우 (4-1)/1 = 3 출력
3  3.00   3.0   0.0 # col2의 경우 예를들어 (8-2)/2 = 3
4 -0.75   3.0  15.0
5 -0.75   3.0  63.0

print(df.pct_change(periods=-1))
>>
   col1  col2    col3
0  0.00  -0.5  0.0000 # col2의 경우 예를들어 (2-1)/2 = -0.5 
1 -0.75  -0.5  0.0000
2  0.00  -0.5  0.0000
3  3.00  -0.5 -0.9375
4  0.00  -0.5 -0.7500
5   NaN   NaN     NaN

fill_method='ffill'인 경우는 기본값으로 바로 윗값으로 결측치를 대체한다.
fill_method='bfill'인 경우는 바로 아랫값으로 결측치를 대체한다.

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

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

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

import numba
...
data = {'col1':[1,2,3,4],'col2':[3,7,5,6]}
idx = ['row1','row2','row3','row4']
df = pd.DataFrame(data = data, index = idx)
print(df)
>>
      col1  col2
row1     1     3
row2     2     7
row3     3     5
row4     4     6

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을 진행

print(df.expanding(min_periods=4).sum())
>>
      col1  col2
row1   NaN   NaN
row2   NaN   NaN
row3   NaN   NaN
row4  10.0  21.0

#열기준 누적값 계산
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

#Numba는 파이썬 코드를 LLVM컴파일러를 이용해 머신코드로 바꾸어 수치연산을 가속해주는 라이브러리
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

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)
>>
      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

print(df.rolling(window=3).sum()) # 뒤에 추가 메서드를 이용하여 연산을 지정해주어야합니다.
>>
      col1
row1   NaN # min_period의 크기는 지정하지 않을경우 window크기와 동일하므로 NaN출력
row2   NaN 
row3   6.0 # 1행, 2행, 3행의 sum값 출력
row4   9.0 # 2행, 3행, 4행의 sum값 출력
row5  12.0
row6  15.0

'''
left : 3 ≤ x < 6
right : 3 < x ≤ 6
both : 3 ≤ x ≤ 6
neither : 3 < x < 6
'''

print(df.rolling(window=3, closed='left').sum())
>>
      col1
row1   NaN
row2   NaN
row3   NaN
row4   6.0
row5   9.0
row6  12.0

print(df.rolling(window=3, closed='right').sum())
>>
      col1
row1   NaN
row2   NaN
row3   6.0
row4   9.0
row5  12.0
row6  15.0

print(df.rolling(window=3, closed='both').sum())
>>
      col1
row1   NaN
row2   NaN
row3   6.0
row4  10.0
row5  14.0
row6  18.0

print(df.rolling(window=3, closed='neither').sum())
>>
      col1
row1   NaN
row2   NaN
row3   NaN
row4   NaN
row5   NaN
row6   NaN

print(df.rolling(window=3, closed='neither',min_periods=2).sum()) # min_period 지정
>>
      col1
row1   NaN
row2   NaN
row3   3.0
row4   5.0
row5   7.0
row6   9.0

print(df.rolling(window=3, center=True).sum())
>>
      col1
row1   NaN
row2   6.0
row3   9.0
row4  12.0
row5  15.0
row6   NaN
print(df.rolling(window=3, win_type='triang').sum()) # 삼각함수로 가중치 부여
>>
      col1
row1   NaN
row2   NaN
row3   4.0
row4   6.0
row5   8.0
row6  10.0

print(df.rolling(window=3, win_type='gaussian').sum(std=3)) # 가우시안 분포로 가중치 부여
>>
           col1
row1        NaN
row2        NaN
row3   5.783838
row4   8.675757
row5  11.567676
row6  14.459595

print(df.rolling(window='60T',on='col2').sum())
>>
      col1              col2
row1   1.0  2022-01-13 00:00 # col2를 기준으로 rolling이 수행됨
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

groupby

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     5     0     7
1      A     2     6     2
2      B     1     1     8
3      B     1     6     6
4      B     3     2     3
5      C     1     0     8
6      C     8     4     1
7      C     1     5     5
8      D     3     3     7
9      D     5     7     7
10     D     1     6     5
11     D     4     0     0
12     E     0     5     6
13     E     2     7     7
14     E     0     7     0

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

print(df.groupby('index').count())
>>
       col1  col2  col3
index                  
A         2     2     2
B         3     3     3
C         3     3     3
D         4     4     4
E         3     3     3

print(df.groupby('index').agg(['sum','mean']))
>>
      col1           col2           col3          
       sum      mean  sum      mean  sum      mean
index                                             
A        7  3.500000    6  3.000000    9  4.500000
B        5  1.666667    9  3.000000   17  5.666667
C       10  3.333333    9  3.000000   14  4.666667
D       13  3.250000   16  4.000000   19  4.750000
E        2  0.666667   19  6.333333   13  4.333333
def top (df,n=2,col='col1'):
    return df.sort_values(by=col)[-n:] #상위 n개 열을 반환하는 함수 top 생성

print(df.groupby('index').apply(top))
>>
         index  col1  col2  col3 # 인덱스와 index열이 중복
index                           
A     1      A     2     6     2
      0      A     5     0     7
B     3      B     1     6     6
      4      B     3     2     3
C     7      C     1     5     5
      6      C     8     4     1
D     11     D     4     0     0
      9      D     5     7     7
E     14     E     0     7     0
      13     E     2     7     7

print(df.groupby('index',group_keys=False).apply(top))
>>
   index  col1  col2  col3 # 인덱스와의 중복이 제거
1      A     2     6     2
0      A     5     0     7
3      B     1     6     6
4      B     3     2     3
7      C     1     5     5
6      C     8     4     1
11     D     4     0     0
9      D     5     7     7
14     E     0     7     0
13     E     2     7     7

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'] # 값은 A~E 까지 있지만, 카테고리는 F까지 지정함.

print(df['col1'].groupby(df_cat).count())
>>
A    2
B    3
C    3
D    4
E    3
F    0 # index열에는 없지만, F까지 category 되었음. observed=False(기본값)인 경우 카테고리 전체가 표시됨.
Name: col1, dtype: int64

print(df['col1'].groupby(df_cat,observed=True).count())
>>
A    2
B    3
C    3
D    4
E    3
Name: col1, dtype: int64

print(df.groupby(['index'],as_index=False).sum())
>>
  index  col1  col2  col3
0     A     7     6     9
1     B     5     9    17
2     C    10     9    14
3     D    13    16    19
4     E     2    19    13

df.loc[6,'index'] = np.NaN
print(df)
>>
   index  col1  col2  col3
0      A     5     0     7
1      A     2     6     2
2      B     1     1     8
3      B     1     6     6
4      B     3     2     3
5      C     1     0     8
6    NaN     8     4     1
7      C     1     5     5
8      D     3     3     7
9      D     5     7     7
10     D     1     6     5
11     D     4     0     0
12     E     0     5     6
13     E     2     7     7
14     E     0     7     0

print(df.groupby('index').sum())
>>
       col1  col2  col3
index                  
A         7     6     9
B         5     9    17
C         2     5    13
D        13    16    19
E         2    19    13

print(df.groupby('index',dropna=False).sum())
>>
       col1  col2  col3
index                  
A         7     6     9
B         5     9    17
C         2     5    13
D        13    16    19
E         2    19    13
NaN       8     4     1 # NaN이 표시됩니다.

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'])
print(df)
>>
           col1  col2  col2
lv0  lv1                   
idx1 row1     7     3     7
     row2     2     1     6
idx2 row1     1     7     2
     row2     3     5     7
     row3     5     1     8

print(df.groupby(level=1).sum())
>>
      col1  col2  col2
lv1                   
row1     8    10     9
row2     5     6    13
row3     5     1     8

print(df.groupby(['lv1','lv0']).sum())
>>
           col1  col2  col2
lv1  lv0                   
row1 idx1     7     3     7
     idx2     1     7     2
row2 idx1     2     1     6
     idx2     3     5     7
row3 idx2     5     1     8

ewm

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

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() # 그래프 출력

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은 기간을 지정하여 평활계수를 계산하는 인수입니다. 계산식은 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 은 질량중심 감쇠법으로 평활계수를 계산하는 인수이다. 계산식은 a=1/(1+com)으로 com이 커질수록 a가 작아진다.

df2 = df.assign(com_2=df['val'].ewm(com=2).mean())
df3 = df.assign(com_10=df['val'].ewm(com=10).mean())
ax = df.plot(kind='bar',x='index',y='val')
ax2= df2.plot(kind='line',x='index', y='com_2', color='red', ax=ax)
ax3= df3.plot(kind='line',x='index', y='com_10', color='green', ax=ax)
plt.show()

com이 큰 녹색이 com이 작은 적색보다 덜 민감하게 반응하는 것을 확인할 수 있다.
com이 클 수록 과거의 데이터의 가중치가 커지기 때문이다.

 

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

df2 = df.assign(harf_2=df['val'].ewm(halflife=2).mean())
df3 = df.assign(harf_5=df['val'].ewm(halflife=5).mean())
ax = df.plot(kind='bar',x='index',y='val')
ax2= df2.plot(kind='line',x='index', y='harf_2', color='red', ax=ax)
ax3= df3.plot(kind='line',x='index', y='harf_5', color='green', ax=ax)
plt.show()

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

 

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()

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 ] 이다.

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 의 여부에 따라 그래프가 달라지는것을 볼 수 있다.


 

728x90