본문 바로가기
Sketch (Programming Language)/Python

Pandas(2)

by 생각하는 이상훈 2023. 8. 21.
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

'Sketch (Programming Language) > Python' 카테고리의 다른 글

Baekjoon Training #14888  (0) 2023.08.27
Pandas(3)  (0) 2023.08.23
Pandas(1)  (0) 2023.08.20
Baekjoon Training #1904  (0) 2023.08.18
Baekjoon Training #12865  (0) 2023.08.06