일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- hive
- matplotlib
- PANDAS
- dataframe
- Google Spreadsheet
- google apps script
- Google Excel
- Excel
- 파이썬
- Python
- numpy
- Java
- math
- list
- PySpark
- Tkinter
- gas
- Apache
- array
- Github
- Kotlin
- Mac
- string
- SQL
- Redshift
- GIT
- django
- c#
- PostgreSQL
- Today
- Total
달나라 노트
Python Pandas : shift (행 위치 옮기기) 본문
Pandas의 shift method는 DataFrame이나 Series에 적용해서 행의 위치를 일정 칸수씩 이동시킵니다.
바로 예시를 통해 알아봅시다.
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
7, 8, 9, 10,
11, 12, 13,
14, 15, 16
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_shifted = df_test.shift(-1)
print(df_shifted)
print(type(df_shifted))
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 7
7 2 a 2050 8
8 2 b 2000 9
9 2 b 2200 10
10 3 a 3000 11
11 3 a 3100 12
12 3 b 3200 13
13 4 a 4200 14
14 4 b 4100 15
15 4 b 4150 16
col1 col2 col3 col4
0 1.0 a 1100.0 2.0
1 1.0 a 1200.0 3.0
2 1.0 b 1300.0 4.0
3 1.0 b 1050.0 5.0
4 1.0 b 1100.0 6.0
5 2.0 a 2100.0 7.0
6 2.0 a 2050.0 8.0
7 2.0 b 2000.0 9.0
8 2.0 b 2200.0 10.0
9 3.0 a 3000.0 11.0
10 3.0 a 3100.0 12.0
11 3.0 b 3200.0 13.0
12 4.0 a 4200.0 14.0
13 4.0 b 4100.0 15.0
14 4.0 b 4150.0 16.0
15 NaN NaN NaN NaN
<class 'pandas.core.frame.DataFrame'>
위 예시는 df_test라는 DataFrame을 생성한 후 이 DataFrame에 shift를 적용한 것입니다.
df_shifted를 보면 DataFrame의 모든 행의 값이 하나씩 위로 올라간걸 볼 수 있습니다.
하나씩 위로 올라간것은 shift의 인자로서 -1이 적혔기 때문이고, -1은 위쪽으로 한칸씩 옮기라는 뜻입니다.
현재 index보다 1씩 작은(-1) index의 위치로 옮기라는 것입니다.
그리고 index=15인 행은 다음 행이 없으니 NaN값으로 표시된 것을 알 수 있죠.
또한 shift가 적용된 대상이 DataFrame인 df_test이므로 return되는 데이터도 DataFrame입니다.
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
7, 8, 9, 10,
11, 12, 13,
14, 15, 16
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_shifted = df_test.shift(1)
print(df_shifted)
print(type(df_shifted))
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 7
7 2 a 2050 8
8 2 b 2000 9
9 2 b 2200 10
10 3 a 3000 11
11 3 a 3100 12
12 3 b 3200 13
13 4 a 4200 14
14 4 b 4100 15
15 4 b 4150 16
col1 col2 col3 col4
0 NaN NaN NaN NaN
1 1.0 a 1000.0 1.0
2 1.0 a 1100.0 2.0
3 1.0 a 1200.0 3.0
4 1.0 b 1300.0 4.0
5 1.0 b 1050.0 5.0
6 1.0 b 1100.0 6.0
7 2.0 a 2100.0 7.0
8 2.0 a 2050.0 8.0
9 2.0 b 2000.0 9.0
10 2.0 b 2200.0 10.0
11 3.0 a 3000.0 11.0
12 3.0 a 3100.0 12.0
13 3.0 b 3200.0 13.0
14 4.0 a 4200.0 14.0
15 4.0 b 4100.0 15.0
<class 'pandas.core.frame.DataFrame'>
반면에 shift의 인자로 1을 전달하면 모든 행의 값이 아래쪽으로 1칸씩 밀린 것을 알 수 있습니다.
index=0인 행은 이전 행이 없으므로 NaN으로 표시되었습니다.
이렇게 몇 칸을 옮기고싶은지에 대한 숫자를 shift의 인자로서 전달하면 원하는 만큼 이동이 가능합니다.
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
6, 7, 8, 9,
10, 11, 12,
13, 14, 15
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_shifted = df_test.loc[:, 'col4'].shift(-1)
print(df_shifted)
print(type(df_shifted))
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 6
7 2 a 2050 7
8 2 b 2000 8
9 2 b 2200 9
10 3 a 3000 10
11 3 a 3100 11
12 3 b 3200 12
13 4 a 4200 13
14 4 b 4100 14
15 4 b 4150 15
0 2.0
1 3.0
2 4.0
3 5.0
4 6.0
5 6.0
6 7.0
7 8.0
8 9.0
9 10.0
10 11.0
11 12.0
12 13.0
13 14.0
14 15.0
15 NaN
Name: col4, dtype: float64
<class 'pandas.core.series.Series'>
shift는 DataFrame의 하나의 행에만 적용할 수도 있습니다.
위 예시는 df_test의 col4에만 shift를 적용시켰습니다.
loc[:, 'col4']를 보면 column이름인 col4에 대괄호가 쳐져있지 않으므로 이것은 col4를 Series로 반환합니다.
따라서 위 예시에서 shift는 Series에 적용된 것과 같으므로 shift의 return값도 Series입니다.
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
6, 7, 8, 9,
10, 11, 12,
13, 14, 15
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_shifted = df_test.loc[:, ['col4']].shift(-1)
print(df_shifted)
print(type(df_shifted))
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 6
7 2 a 2050 7
8 2 b 2000 8
9 2 b 2200 9
10 3 a 3000 10
11 3 a 3100 11
12 3 b 3200 12
13 4 a 4200 13
14 4 b 4100 14
15 4 b 4150 15
col4
0 2.0
1 3.0
2 4.0
3 5.0
4 6.0
5 6.0
6 7.0
7 8.0
8 9.0
9 10.0
10 11.0
11 12.0
12 13.0
13 14.0
14 15.0
15 NaN
<class 'pandas.core.frame.DataFrame'>
이번엔 loc.[:, ['col4']] 처럼 column이름에 대괄호를 쳐서 loc가 DataFrame을 return하게 했습니다.
따라서 여기에 적용된 shift도 DataFrame에 대해 적용되는 것이므로 shift의 return값도 DataFrame입니다.
shift는 자신이 적용된 대상의 data type과 동일한 data type의 결과를 return합니다.
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
6, 7, 8, 9,
10, 11, 12,
13, 14, 15
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_group_shifted = df_test.groupby(by=['col1', 'col2'])[['col4']].shift(-1)
print(df_group_shifted)
print(type(df_group_shifted))
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 6
7 2 a 2050 7
8 2 b 2000 8
9 2 b 2200 9
10 3 a 3000 10
11 3 a 3100 11
12 3 b 3200 12
13 4 a 4200 13
14 4 b 4100 14
15 4 b 4150 15
col4
0 2.0
1 3.0
2 NaN
3 5.0
4 6.0
5 NaN
6 7.0
7 NaN
8 9.0
9 NaN
10 11.0
11 NaN
12 NaN
13 NaN
14 15.0
15 NaN
<class 'pandas.core.frame.DataFrame'>
shift는 groupby와 함께 사용될 수 있습니다.
위 예시를 보면 col1, col2를 기준으로 groupby를 하고 groupby된 col4에 shift를 적용합니다.
따라서 결과를 보면 shift가 동일한 col1, col2값을 가진 행들의 그룹 내에서 적용된 것을 볼 수 있습니다.
(index=0, 1, 2 행이 동일한 col1, col2 값을 가지고있으므로 index=0, 1, 2에 있는 col4값을 위쪽으로 한 칸씩 올린 모습을 볼 수 있습니다. index=2는 동일한 col1, col2값을 가진 다음 행이 없으므로 NaN으로 표시되는 것도 볼 수 있죠.)
import pandas as pd
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
6, 7, 8, 9,
10, 11, 12,
13, 14, 15
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_test.loc[:, 'col5'] = df_test.groupby(by=['col1'])['col3'].shift(-2)
print(df_test)
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 6
7 2 a 2050 7
8 2 b 2000 8
9 2 b 2200 9
10 3 a 3000 10
11 3 a 3100 11
12 3 b 3200 12
13 4 a 4200 13
14 4 b 4100 14
15 4 b 4150 15
col1 col2 col3 col4 col5
0 1 a 1000 1 1200.0
1 1 a 1100 2 1300.0
2 1 a 1200 3 1050.0
3 1 b 1300 4 1100.0
4 1 b 1050 5 NaN
5 1 b 1100 6 NaN
6 2 a 2100 6 2000.0
7 2 a 2050 7 2200.0
8 2 b 2000 8 NaN
9 2 b 2200 9 NaN
10 3 a 3000 10 3200.0
11 3 a 3100 11 NaN
12 3 b 3200 12 NaN
13 4 a 4200 13 4150.0
14 4 b 4100 14 NaN
15 4 b 4150 15 NaN
위같은 방식으로 groupby와 shift로 이동된 데이터를 원본 DataFrame의 어떤 column에 할당할 수도 있습니다.
import pandas as pd
dict_test = {
'col1': [
1, 1, 1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3,
4, 4, 4
],
'col2': [
'a', 'a', 'a', 'b', 'b', 'b',
'a', 'a', 'b', 'b',
'a', 'a', 'b',
'a', 'b', 'b'
],
'col3': [
1000, 1100, 1200, 1300, 1050, 1100,
2100, 2050, 2000, 2200,
3000, 3100, 3200,
4200, 4100, 4150
],
'col4': [
1, 2, 3, 4, 5, 6,
6, 7, 8, 9,
10, 11, 12,
13, 14, 15
]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_rolling_sum_1 = df_test.groupby(by=['col1', 'col2'])[['col4']].rolling(2).apply(sum)
print(df_rolling_sum_1)
print(type(df_rolling_sum_1))
df_rolling_sum_2 = df_test.groupby(by=['col1', 'col2'])[['col4']].rolling(2).apply(sum).shift(-1)
print(df_rolling_sum_2)
print(type(df_rolling_sum_2))
-- Result
col1 col2 col3 col4
0 1 a 1000 1
1 1 a 1100 2
2 1 a 1200 3
3 1 b 1300 4
4 1 b 1050 5
5 1 b 1100 6
6 2 a 2100 6
7 2 a 2050 7
8 2 b 2000 8
9 2 b 2200 9
10 3 a 3000 10
11 3 a 3100 11
12 3 b 3200 12
13 4 a 4200 13
14 4 b 4100 14
15 4 b 4150 15
col4
col1 col2
1 a 0 NaN
1 3.0
2 5.0
b 3 NaN
4 9.0
5 11.0
2 a 6 NaN
7 13.0
b 8 NaN
9 17.0
3 a 10 NaN
11 21.0
b 12 NaN
4 a 13 NaN
b 14 NaN
15 29.0
<class 'pandas.core.frame.DataFrame'>
col4
col1 col2
1 a 0 3.0
1 5.0
2 NaN
b 3 9.0
4 11.0
5 NaN
2 a 6 13.0
7 NaN
b 8 17.0
9 NaN
3 a 10 21.0
11 NaN
b 12 NaN
4 a 13 NaN
b 14 29.0
15 NaN
<class 'pandas.core.frame.DataFrame'>
shift는 rolling과도 같이 사용될 수 있습니다.
위 예시를 보면 col1, col2를 기준으로 그룹화된 DataFrame의 col4에 2개 행(현재행, 그 이전행)에 대해 rolling sum을 진행한 것이 df_rolling_sum_1이고,
여기에 shift를 추가로 적용한게 df_rolling_sum_2입니다.
이 두 결과를 비교해보면 데이터는 똑같으나 shift(-1)이 적용된 결과는 동일한 group(=동일한 col1, col2 값을 가진 행들) 내에서 col4의 rooling sum 값이 한줄씩 위로 옮겨긴걸 볼 수 있습니다.
import pandas as pd
dict_test = {
'col1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'col2': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b'],
'col3': [1000, 1200, 1100, 1050, 1300, 900, 1500, 2000, 1800, 1600]
}
df_test = pd.DataFrame(dict_test)
print(df_test)
df_rolling_sum = df_test.groupby(by=['col2'])[['col3']].rolling(2).apply(sum).shift(-1)
df_rolling_sum = df_rolling_sum.reset_index(drop=False, inplace=False)
print(df_rolling_sum)
print(type(df_rolling_sum))
df_test.loc[:, 'new_col3'] = df_rolling_sum.loc[:, 'col3']
print(df_test)
print(type(df_test))
-- Result
col1 col2 col3
0 1 a 1000
1 2 a 1200
2 3 a 1100
3 4 a 1050
4 5 b 1300
5 6 b 900
6 7 b 1500
7 8 b 2000
8 9 b 1800
9 10 b 1600
col2 level_1 col3
0 a 0 2200.0
1 a 1 2300.0
2 a 2 2150.0
3 a 3 NaN
4 b 4 2200.0
5 b 5 2400.0
6 b 6 3500.0
7 b 7 3800.0
8 b 8 3400.0
9 b 9 NaN
<class 'pandas.core.frame.DataFrame'>
col1 col2 col3 new_col3
0 1 a 1000 2200.0
1 2 a 1200 2300.0
2 3 a 1100 2150.0
3 4 a 1050 NaN
4 5 b 1300 2200.0
5 6 b 900 2400.0
6 7 b 1500 3500.0
7 8 b 2000 3800.0
8 9 b 1800 3400.0
9 10 b 1600 NaN
<class 'pandas.core.frame.DataFrame'>
위 예시는 rolling sum과 shift를 적용한 결과를 df_test의 new_col3라는 새로운 컬럼에 할당하고 있는 예시입니다.
보시면 rolling sum + shift(-1)의 결과로 생성된 df_rolling_sum의 col3의 값이 df_test의 new_col3에 그대로 할당된것을 볼 수 있죠.
'Python > Python Pandas' 카테고리의 다른 글
Python Pandas : to_list (Series를 list type으로 만들기) (0) | 2021.10.27 |
---|---|
Python Pandas : Tabulate, DataFrame을 가독성 좋게 print하기 (tabulate library 이용. pretty print dataframe) (1) | 2021.10.23 |
Python Pandas : to_json (Series 또는 DataFrame을 json 형태로 변환하기) (0) | 2021.09.14 |
Python Pandas : duplicated (중복값 확인하기) (0) | 2021.08.31 |
Python Pandas : iterrows (DataFrame의 행 반복하기) (0) | 2021.08.23 |