2025-05-12

장상희·2025년 5월 12일
0

파이썬

목록 보기
22/31

기간/데이터 쉬프트 (shift)

shift메서드는 시계열 데이터의 데이터나 인덱스를 원하는 기간만큼 쉬프트 하는 메서드 입니다.

freq 인수를 입력하지 않으면 데이터가 이동하고, 인수값을 입력하게되면 인덱스가 freq값 만큼 이동하게됩니다.

periods : 이동할 기간입니다.

freq : 입력 할 경우 인덱스가 이동하게 됩니다. Y, M, D, H, T, S 나 Timestamp, 'Infer'등이 올 수 있습니다.

fill_value : shift로 인해 생긴 결측치를 대체할 값입니다.

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

pd.date_range를 이용해 기준시간에 대해 일정 간격을 가진 datetime index를 생성하겠습니다.

idx = pd.date_range(start='2022-01-01',periods=5,freq='2D')
# 2일 간격으로 5행의 인덱스 생성
data={'col1':[10,20,30,40,50],'col2':[1,3,6,7,9],'col3':[43,13,82,47,31]}
df = pd.DataFrame(data=data, index=idx)
print(df)
>>
            col1  col2  col3
2022-01-01    10     1    43
2022-01-03    20     3    13
2022-01-05    30     6    82
2022-01-07    40     7    47
2022-01-09    50     9    31

period 인수 사용할 경우 행 기준으로 이동

print(df.shift(periods=2,))
>>
            col1  col2  col3
2022-01-01   NaN   NaN   NaN
2022-01-03   NaN   NaN   NaN
2022-01-05  10.0   1.0  43.0
2022-01-07  20.0   3.0  13.0
2022-01-09  30.0   6.0  82.0

axis 사용

print(df.shift(periods=2,axis=1))
>>
            col1  col2  col3
2022-01-01   NaN   NaN    10
2022-01-03   NaN   NaN    20
2022-01-05   NaN   NaN    30
2022-01-07   NaN   NaN    40
2022-01-09   NaN   NaN    50

fill_value 인수를 사용하면, shift되면서 NaN처리된 결측치를 원하는 값으로 채울 수 있습니다.

print(df.shift(periods=2, axis=1,fill_value='-'))
>>
           col1 col2 col3
2022-01-01    -    -   10
2022-01-03    -    -   20
2022-01-05    -    -   30
2022-01-07    -    -   40
2022-01-09    -    -   50

freq 인수의 사용

freq 인수를 설정해주면, 데이터가 아닌 인덱스가 freq에 입력한 값 만큼 쉬프트 됩니다.

print(df.shift(periods=3,freq='D'))
# 일 기준 3기간 이동. 즉, 3일 이동
>>
#인덱스에 있는 년도와 날짜가 3일씩 이동된걸 알 수 있다
            col1  col2  col3
2022-01-04    10     1    43
2022-01-06    20     3    13
2022-01-08    30     6    82
2022-01-10    40     7    47
2022-01-12    50     9    31

freq='infer'인 경우, 현재 인덱스의 간격을 분석해서 적당한 freq를 추론해줍니다.

print(df.shift(periods=3,freq='infer'))
#인덱스의 날짜 간격이 처음 데이터프레임을 생성할때 2D라는 간격으로 설정했기 때문에 
#infer로 추론한 간격은 2D가 된다
>>
            col1  col2  col3
2022-01-07    10     1    43
2022-01-09    20     3    13
2022-01-11    30     6    82
2022-01-13    40     7    47
2022-01-15    50     9    31

위의 예시의 경우, 인덱스의 인터벌(간격)이 2일이므로 freq='2D'로 추론하였으며, period=3이기 때문에 6일이 쉬프트 된것을 알 수 있습니다.

period로 변환 (to_period)

DatetimeIndex와 PeriodIndex의 차이는 Datetimeindex는 연,월,일과 같은 모든 시간을 표시하지만 Periodindex는 그중에서 잘라서 출력해 줄 수 있

to_period 메서드는 DatetimeIndex를 PeriodIndex로 변환하는 메서드 입니다.

freq : 원하는 시간 단위로 변환할 수 있습니다.

axis : 변환할 기준 축 입니다.

copy : 사본을 형성할지 여부입니다.

idx = pd.date_range(start='2021-08-01',periods=5,freq='45D') # 45일 간격 인덱스
>>
DatetimeIndex(['2021-08-01', '2021-09-15', '2021-10-30', '2021-12-14',
               '2022-01-28'],
              dtype='datetime64[ns]', freq='45D') # 형식은 datetime64

freq값을 지정하여 원하는 시간간격으로 출력이 가능합니다.

freq="Y"

print(idx.to_period("Y"))
>>
PeriodIndex(['2021', '2021', '2021', '2021', '2022'], dtype='period[A-DEC]')

freq="M"

print(idx.to_period("M"))
>>
PeriodIndex(['2021-08', '2021-09', '2021-10', '2021-12', '2022-01'], dtype='period[M]')

freq="W"

print(idx.to_period("W"))
>>
PeriodIndex(['2021-07-26/2021-08-01', '2021-09-13/2021-09-19',
             '2021-10-25/2021-10-31', '2021-12-13/2021-12-19',
             '2022-01-24/2022-01-30'],
            dtype='period[W-SUN]')

freq="H"

print(idx.to_period("H"))
>>
PeriodIndex(['2021-08-01 00:00', '2021-09-15 00:00', '2021-10-30 00:00',
             '2021-12-14 00:00', '2022-01-28 00:00'],
            dtype='period[H]')

하위분류반환 (xs)

xs는 멀티인덱스 객체에 대해서 하위 분류를 출력하는 메서드입니다.

key : 분류의 기준이 되는 값입니다. Multi Index의 값을 지정합니다.

axis : 하위 분류 출력의 기준이되는 축을 지정합니다.

level : 멀티인덱스에 키가 부분적으로 포함되어있는경우, 레벨 지정을 통해 분류할 수 있습니다.

drop_level : 기본값은 True로 필터링하는 값을 제외하고 하위 분류만 출력합니다. False면 필터링하는 값이 있는 분류까지 출력합니다.

data = {'col1':[0,1,2,3,4], 'col2':[5,6,7,8,9],
        'level0':['A','A','A','B','B'],
        'level1':['X','X','Y','Y','Z'],
        'level2':['a','a','b','c','a']}
df = pd.DataFrame(data=data)
df = df.set_index(['level0', 'level1', 'level2'])
print(df)
>>
                      col1  col2
level0 level1 level2
A      X      a          0     5
              a          1     6
       Y      b          2     7
B      Y      c          3     8
       Z      a          4     9

기본적인 사용법

기본적으로 key값을 지정하면 해당 값의 하위 분류를 출력합니다.

print(df.xs(key='A'))
>>
               col1  col2
level1 level2
A      X      a          0     5
              a          1     6
       Y      b          2     7
#B      Y      c          3     8
#       Z      a          4     9
#여기는 제외된

key값을 여러 값으로 지정할 수 도 있습니다.

print(df.xs(key=('A','X')))#의 하위분류를 하기 때문에
>>

        col1  col2
level2            
a          0     5
a          1     6

                      col1  col2
level0 level1 level2
A      X      /a          0     5
              /a          1     6
       Y      /b          2     7
				      ////////////////////
B      Y      c          3     8
       Z      a          4     9

level을 지정하여 하위분류를 진행할 수 있습니다.

print(df.xs(key='Y',level=1))
>>
               col1  col2
level0 level2            
A      b          2     7
B      c          3     8

                      col1  col2
level0 level1 level2
A      X      a          0     5
              a          1     6
/////////////////////////////////
       Y!      b          2     7
B      Y!      c          3     8
/////////////////////////////////
       Z      a          4     9

drop_level=True로 할 경우 key값으로 지정된 레벨을 포함해서 줄력합니다.

print(df.xs(key='Y',level=1,drop_level=True)) #False가 기본이다 
>>
                      col1  col2
level0 level1 level2
A      Y      b          2     7
B      Y      c          3     8

피벗화, 열의 인덱스화 (stack)

stack 메서드는 열을 피벗하여 하위 인덱스로 변환하는 메서드입니다.

level : MultiColumns의 경우 하위인덱스로 변환할 열의 레벨입니다. 기본값은 -1로 최하위 레벨이 선택됩니다. dropna : {True / False} 기본값은 True로 피벗화로인해 생성된 하위인덱스의 모든 값이 결측치(NaN)인 경우 해당 열이 제거됩니다.

data = [[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]
idx = [['idx1','idx1','idx2','idx2'],['row1','row2','row3','row4']]
col = [['val1','val1','val2','val2'],['col1','col2','col3','col4']]
df = pd.DataFrame(data = data, index = idx, columns = col)
print(df)
>>
           val1      val2
           col1 col2 col3 col4
idx1 row1     0    1    2    3
     row2     4    5    6    7
idx2 row3     8    9   10   11
     row4    12   13   14   15

기본적인 사용법

'level'의 기본값은 '-1'로 최하위 레벨이 선택됩니다. 위 df에서는 level=1이 최하위 계층이기 때문에,

df.stack( ) = df.stack(level=1) 입니다. 함수 실행 시 level=1의 열이 인덱스로 피벗된걸 확인할 수 있습니다.

print(df.stack())# 있지 않은 값은 결측값이 된걸 볼 수 있다
>>
                val1  val2
idx1 row1 col1   0.0   NaN
          col2   1.0   NaN
          col3   NaN   2.0
          col4   NaN   3.0
     row2 col1   4.0   NaN
          col2   5.0   NaN
          col3   NaN   6.0
          col4   NaN   7.0
idx2 row3 col1   8.0   NaN
          col2   9.0   NaN
          col3   NaN  10.0
          col4   NaN  11.0
     row4 col1  12.0   NaN
          col2  13.0   NaN
          col3   NaN  14.0
          col4   NaN  15.0

level=0인 경우 아래와같이 'val1', 'val2'가 포함된 level=0의 열이 피벗화 되는것을 볼 수 있습니다.

print(df.stack(level=0))# 레벨 0일 경우 val1,val2가 피벗화 된걸 확인 할 수 있다
>>
                col1  col2  col3  col4
idx1 row1 val1   0.0   1.0   NaN   NaN
          val2   NaN   NaN   2.0   3.0
     row2 val1   4.0   5.0   NaN   NaN
          val2   NaN   NaN   6.0   7.0
idx2 row3 val1   8.0   9.0   NaN   NaN
          val2   NaN   NaN  10.0  11.0
     row4 val1  12.0  13.0   NaN   NaN
          val2   NaN   NaN  14.0  15.0

level=(0,1)처럼 튜플로 묶어줄 경우 해당되는 모든 계층에 대해 피벗화를 할 수 있습니다.

모든 계층(레벨)이 피벗화 될 경우 Serise 객체로 출력됩니다.

print(df.stack(level=(0,1))) 
>>
idx1  row1  val1  col1     0.0
                  col2     1.0
            val2  col3     2.0
                  col4     3.0
      row2  val1  col1     4.0
                  col2     5.0
            val2  col3     6.0
                  col4     7.0
idx2  row3  val1  col1     8.0
                  col2     9.0
            val2  col3    10.0
                  col4    11.0
      row4  val1  col1    12.0
                  col2    13.0
            val2  col3    14.0
                  col4    15.0
dtype: float64

dropna인수의 사용

dropna인수는 기본값이 True로 열이 피벗화된 인덱스의 값이 NaN이면 해당 열을 출력하지 않습니다.

예시를 위해 간단한 2x2 짜리 데이터를 만들어보겠습니다.

data = [[np.NaN,1],[2,3]]
idx = ['row1','row2']
col = ['col1','col2']
df = pd.DataFrame(data = data, index = idx, columns = col)
print(df)
>>
      col1  col2
row1   NaN     1
row2   2.0     3

stack메서드를 사용할 경우 col1col2 열이 인덱스로 피벗화되는데, row1-col1의 값은 NaN이기 때문에 출력에서는 아래와같이 제거됩니다.

print(df.stack())#결측값이 제거된걸 볼 수 있다, 모든 열이 피벗화가 되었기 때문에 시리즈로 출력한다
>>
row1  col2    1.0 
row2  col1    2.0
      col2    3.0
dtype: float64

dropna=True로 출력 할 경우 결측값을 갖는 열 또한 정상적으로 출력되는것을 볼 수 있습니다.

print(df.stack(dropna=False))#결측값이 포함되어 정상적으로 출력되는걸 확인할 수 있다
>>
row1  col1    NaN
      col2    1.0
row2  col1    2.0
      col2    3.0
dtype: float64

언피벗화, 행의 열로 변환 (unstack)

unstack 메서드는 행을 언피벗하여 하위 열로 변환하는 메서드입니다.

level : MultiIndex의 경우 하위열로 변환할 행의 레벨입니다. 기본값은 -1로 최하위 레벨이 선택됩니다.

fill_value : 생성된 열의 값에 결측치가 있을 경우 대체할 값입니다.

data =[1,2,3,4,5]
idx = [['idx1','idx1','idx2','idx2','idx2'],['row1','row2','row1','row2','row3']]
df = pd.Series(data=data, index = idx)
print(df)
>>
idx1  row1    1
      row2    2
idx2  row1    3
      row2    4
      row3    5
dtype: int64

level은 기본값이 -1이며, 최하위 레벨의 행에 대해 열로 언피벗 합니다.

아래 예시를 보면 최 하위 계층인 row1,row2가 속한 인덱스가 열로 언피벗 된것을 확인할 수 있습니다.

print(df.unstack()) #출력을 보면 row가 위로 올라가면서 언피벗된걸 확인할 수 있
>>
      row1  row2  row3
idx1   1.0   2.0   NaN
idx2   3.0   4.0   5.0

fill_value 인수를 사용할 경우, 언피벗으로 인해 행성된 결측치를 특정 값으로 지정할 수 있습니다.

print(df.unstack(fill_value='-'))#결측값을 특정 값으로 지정해준다 피벗화에서도 똑같이 가능하다
>>
     row1 row2 row3
idx1    1    2    -
idx2    3    4    5

좀 더 큰 다중인덱스에 대해서 예시를 들어보기위해 4레벨의 멀티인덱스를 생성해보겠습니다.

data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
level0=['idx1','idx1','idx1','idx1','idx1','idx1','idx1','idx1',
        'idx2','idx2','idx2','idx2','idx2','idx2','idx2','idx2']
level1=['row1','row1','row1','row1','row2','row2','row2','row2',
        'row3','row3','row3','row3','row4','row4','row4','row4']
level2=['val1','val1','val2','val2','val1','val1','val2','val2',
        'val1','val1','val2','val2','val1','val1','val2','val2']
level3=['col1','col2','col3','col4','col1','col2','col3','col4',
        'col1','col2','col3','col4','col1','col2','col3','col4']
idx = [level0,level1,level2,level3]
df = pd.Series(data =data, index =idx)
print(df)
>>
idx1  row1  val1  col1     0
                  col2     1
            val2  col3     2
                  col4     3
      row2  val1  col1     4
                  col2     5
            val2  col3     6
                  col4     7
idx2  row3  val1  col1     8
                  col2     9
            val2  col3    10
                  col4    11
      row4  val1  col1    12
                  col2    13
            val2  col3    14
                  col4    15
dtype: int64

val1val2가 속한 level=2로 unstack메서드를 실행해보겠습니다.

print(df.unstack(level=2))#level=2가 언피벗화가 된걸 확일할 수 있다
>>
                val1  val2
idx1 row1 col1   0.0   NaN
          col2   1.0   NaN
          col3   NaN   2.0
          col4   NaN   3.0
     row2 col1   4.0   NaN
          col2   5.0   NaN
          col3   NaN   6.0
          col4   NaN   7.0
idx2 row3 col1   8.0   NaN
          col2   9.0   NaN
          col3   NaN  10.0
          col4   NaN  11.0
     row4 col1  12.0   NaN
          col2  13.0   NaN
          col3   NaN  14.0
          col4   NaN  15.0

level에 튜플을 이용하여 Multi Columns로 unstack을 실행할 수 있습니다.

print(df.unstack(level=(2,3)))
>>
          col1 col2 col3 col4
idx1 row1    0    1    2    3
     row2    4    5    6    7
idx2 row3    8    9   10   11
     row4   12   13   14   15

인덱스 순서변경 (swaplevel)

swaplevel메서드는 Multi Index (또는 Munti Columns)에서 두 인덱스의 순서를 변경하는 메서드입니다.

i , j : 순서를 변경할 두 인덱스의 레벨입니다. 기본적으로 제일 낮은 두 레벨의 인덱스가 교환됩니다.(-2, -1)

axis : 기본값은 0으로 axis=1로 변경할 경우 Multi Columns에 대해 메서드가 수행됩니다.

data = {'col':[0,1,2,3,4,5]}
level0 = ['idx1','idx1','idx1','idx1','idx2','idx2']
level1 = ['val1','val1','val2','val2','val3','val4']
level2 = ['row1','row2','row3','row4','row5','row6']
idx = [level0, level1, level2]
df = pd.DataFrame(data = data, index=idx)
print(df)
>>
                col
idx1 val1 row1    0
          row2    1
     val2 row3    2
          row4    3
idx2 val3 row5    4
     val4 row6    5

기본적인 사용법

i, j인수에 아무것도 입력하지 않는다면, 제일 낮은 두 레벨의 인덱스가 교환됩니다.

print(df.swaplevel())
>>
                col
idx1 row1 val1    0 # 인덱스의 level1과 level2의 위치가 바뀐것을 확인.
     row2 val1    1
     row3 val2    2
     row4 val2    3
idx2 row5 val3    4
     row6 val4    5

인수로 한 숫자만 입력하게되면, 가장 낮은 레벨의 인덱스와 인수로 입력한 숫자에 해당하는 레벨의 인덱스가 교환됩니다.

print(df.swaplevel(0))
>>
                col
row1 val1 idx1    0 #인덱스의 level0과 최하위 레벨의 인덱스의 위치가 바뀐것을 확인.
row2 val1 idx1    1
row3 val2 idx1    2
row4 val2 idx1    3
row5 val3 idx2    4
row6 val4 idx2    5

두 값을 지정하여 원하는 인덱스끼리의 교환이 가능합니다. 레벨명이 있다면 레벨명을 쓸 수도 있습니다.

print(df.swaplevel(i=0,j=1))#이거는 왜 지정하는지 모르겠다 컬러쪽에 레벨이 하나 더 있어도 axis로 구별을 안하면 행과 열도 같이 스왑 되는게 똑같다 굳이 왜 지정을 해서 바꾸는지 이해를 못함
>>
                col
val1 idx1 row1    0 # 레벨0과 레벨1의 위치가 바뀐것을 확인.
          row2    1
val2 idx1 row3    2
          row4    3
val3 idx2 row5    4
val4 idx2 row6    5

인덱스 제거 (droplevel)

droplevel 메서드는 Multi Index나 Multi Columns에서 특정 레벨을 제거하는 메서드입니다.

level : 제거할 단계 입니다.

axis : 특정 레벨을 제거할 축 입니다.

data= [[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]
idx = [['idx1','idx1','idx2','idx2'],['row1','row2','row3','row4']]
col = [['col1','col1','col2','col2'],['val1','val2','val3','val4']]
df = pd.DataFrame(data=data, index = idx, columns = col)
print(df)
>>
          col1      col2
          val1 val2 val3 val4
idx1 row1    0    1    2    3
     row2    4    5    6    7
idx2 row3    8    9   10   11
     row4   12   13   14   15

기본적인 사용법

level에 제거를 원하는 레벨을 입력함으로서 해당 레벨을 제거하여 값을 출력할 수 있습니다.

level=0인 경우 Multi Index의 level=0인 idx1idx2가 제거된 것을 알 수 있습니다.

print(df.droplevel(axis=0,level=0))
>>
     col1      col2
     val1 val2 val3 val4
row1    0    1    2    3 # idx가 제거됨
row2    4    5    6    7
row3    8    9   10   11
row4   12   13   14   15

level=1인 경우 Multi Index의 level=1인 row1row2row3row4가 제거된 것을 알 수 있습니다.

print(df.droplevel(axis=0,level=1))
>>
     col1      col2
     val1 val2 val3 val4
idx1    0    1    2    3 # row가 제거됨
idx1    4    5    6    7
idx2    8    9   10   11
idx2   12   13   14   15

axis=1인 경우 Multi Columns에 대해서 특정 레벨을 제거 할 수 있습니다.

print(df.droplevel(axis=1,level=0))
>>
           val1  val2  val3  val4 # col이 제거됨
idx1 row1     0     1     2     3
     row2     4     5     6     7
idx2 row3     8     9    10    11
     row4    12    13    14    15
Copyprint(df.droplevel(axis=1,level=1))
>>
           col1  col1  col2  col2 # vol이 제거됨
idx1 row1     0     1     2     3
     row2     4     5     6     7
idx2 row3     8     9    10    11
     row4    12    13    14    15
profile
프로그래머 꿈나무

0개의 댓글