파이썬 버전 3.8 기준
pandas 버전 1.1.1 기준
인덱스 정렬(순서 변경)을 위한 reindex() 메서드 |
본 포스팅에서는 reindex()의 사용법에 다루도록 한다.
reindex()를 사용하여 데이터를 정렬하는 방법부터 누락데이터 처리까지 그리고 상세 옵션을 설명하는 내용도 다루도록 한다.
reindex()메서드 |
pandas에서 reindex() 메서드는 기본적인 데이터 정렬 메서드이다.
○ reindex()는 특정 축을 따라 입력된 레이블 배열에 따라 데이터 순서를 조정한다.
reindex()의 기능을 이용하면 다음과 같은 작업을 수행할 수 있다.
○ 기존에 존재하는 데이터에 레이블의 새로운 세트에 매치시켜 순서를 재조정한다.
○ 레이블은 존재하지만 데이터가 존재하지 않는 레이블 위치에 누락값을 발생시켜 마커 할 수 있다.
○ 만약 필요하다면, 로직을 사용해 레이블이 없는 데이터들을 채울 수 있다.
메서드 사용 형식)
# Series의 경우
result=object1.reindex(index, method=None, fill_value=np.nan, limit=None)
# DataFrame의 경우
result=object1.reindex(index, columns, axis=0, method=None, fill_value=np.nan, limit=None)
각 입력 객체별 설명은 다음과 같다.
○ object1: 데이터를 재정렬할 객체(DataFrame, Series)이다.
○ index: 정렬하는 순서로 구성된 인덱스의 배열(혹은 배열과 유사한array-like)을 입력받는다.
○ method: 위의 index가 object1에 없는 경우 해당 값을 채우는 방식을 입력받는다.
▷ 상세 내용은 아래 섹션에 정리하였다.
○ fill_value: 위의 index가 object1에 없는 경우 해당 값을 채우는 값을 입력받는다.
○ limit: 누락값이 연속적으로 여러 개 존재할 때 method방식에 따라 누락 값을 채우는 개수를 제한한다.
○ axis: 정렬을 수행할 축을 입력받는다. 기본값으로는 행을 기준으로 정렬을 수행한다.
▷ 'index' / 0 : 행에 대해서만 정렬을 수행시킨다.
▷ 'columns' / 1 : 열에 대해서만 정렬을 수행시킨다.
추가적으로 DataFrame에서는 index와 columns 입력변수를 사용하여 각 방향에 대해 인덱스 정렬을 수행할 수 있으며, axis입력변수를 사용하여 한 방향에 대해서만 데이터 정렬을 수행할 수 있다.
reindex()메서드의 기본적인 사용 방식에 대한 예제 |
본 포스팅에서는 다음과 같이 pandas와 numpy를 import시킨 후 예제를 수행하였다.
○ 본 포스팅에서는 numpy는 딱히 쓰지는 않지만 습관적으로 그랬다.
모듈의 임폴트)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
다음은 reindex() 메서드의 가장 단순한 사용 예제를 보여준다.
○ 다음 예제를 보면 입력된 레이블 배열 중에 'f' 레이블은 기존 Series에는 없었다.
○ 따라서 'f' 레이블 결과에서 NaN이 나타난다.
Series에서의 reindex() 사용)
# 예제용 Series 데이터의 정의
In[4]: sample = pd.Series([1.1, 2.2, 3.3, 4.4, 5.5], index=['a', 'b', 'c', 'd', 'e'])
In[5]: sample
Out[5]:
a 1.1
b 2.2
c 3.3
d 4.4
e 5.5
dtype: float64
# reindex() 사용 예제
In[6]: sample.reindex(['e','a','f','d'])
Out[6]:
e 5.5
a 1.1
f NaN
d 4.4
dtype: float64
사용자는 DataFrame에 reindex() 메서드를 사용해 행(row, index)과 열(columns)의 순서를 변경할 수 있다.
이를 수행하기 위해 크게 2가지 방식이 있는데 다음과 같이 설명할 수 있다.
○ index 및 columns 입력변수를 이용하여 두 방향을 동시에 정렬하는 방식
○ 하나의 입력 배열과 axis 입력변수를 사용하여 하나의 방향에 대해 정렬하는 방식(축 스타일 방식)
다음 예제는 위의 두 방식을 어떻게 적용하는지 보여주는 예제이다.
DataFrame에서의 reindex() 메서드의 사용)
# 예제용 DataFrame의 정의
In[7]: sample_df=pd.DataFrame([[1.1, 1.2, 1.3, 1.4], [2.1, 2.2, 2.3, 2.4], [3.1, 3.2, 3.3, 3.4]], index=['a', 'b', 'c'], columns=['A','B','C','D'])
In[8]: sample_df
Out[8]:
A B C D
a 1.1 1.2 1.3 1.4
b 2.1 2.2 2.3 2.4
c 3.1 3.2 3.3 3.4
# reindex() 사용 예제(두방향 동시 정렬)
In[9]: sample_df.reindex(index=['b','a','d'], columns=['B','D','E'])
Out[9]:
B D E
b 2.2 2.4 NaN
a 1.2 1.4 NaN
d NaN NaN NaN
# reindex() 사용 예제(한방향 정렬)
In[10]: sample_df.reindex(['b','a','d'], axis='index')
Out[10]:
A B C D
b 2.1 2.2 2.3 2.4
a 1.1 1.2 1.3 1.4
d NaN NaN NaN NaN
In[11]: sample_df.reindex(['B','A','D'], axis='columns')
Out[11]:
B A D
a 1.2 1.1 1.4
b 2.2 2.1 2.4
c 3.2 3.1 3.4
실제의 축 레이블의 정보를 담고있는 Index 객체는 객체간의 공유가 가능하다.
○ 즉, 다른 객체의 Index 객체를 사용하여 정렬을 수행하는 것이 가능하다.
따라서 사용자가 Series와 DataFrame을 둘 다 정의한 상황에서는 다음 예제와 같이 실행되어질 수 있다.
○ 아래 예제의 Series와 DataFrame은 위의 예제에서 사용한 객체와 동일하다.
○ 아래 예제의 결과는 정렬된 Series의 인덱스가 DataFrame의 인덱스에 따라 같은 파이썬 객체라는 것을 보여준다.
타 객체의 Index 객체를 사용한 데이터 정렬)
# 타 객체의 Index 객체를 이용한 데이터 정렬
In[12]: copy_sample= sample.reindex(sample_df.index)
In[13]: copy_sample
Out[13]:
a 1.1
b 2.2
c 3.3
dtype: float64
# 객체간의 Index 객체 공유
In[14]: copy_sample.index is sample_df.index
Out[14]: True
※ 참고사항
성능에 민감한 코드를 작성할 때, 재인덱싱을 통해 성능(혹은 연산속도)를 개선할 수 있다.
많은 연산들에서 미리 정렬된 데이터에서 작업을 수행하는 것이 더 빠르므로 미리 정렬을 수행해놓으면 좋다.
잦은 reindex로 인해 성능이 저하되는 메커니즘은 다음과 같다.
→ 두 개의 정렬되지 않은 DataFrame을 더하는 것은 내부적으로 reindex 과정을 야기한다.
→ 위 과정에서 사용자는 reindex 과정을 인지하지 못할 수도 있다.
(이는 pandas가 여러 연산에서 reindex를 자동으로 수행하도록 시켜놓았기 때문이다.)
→ 그러나 위의 과정을 반복해야할 필요성이 있을 때에는 재인덱싱을 반복해서 하므로 계산성능의 저하를 일으킬 수 있다.
reindex_like() 메서드를 활용한 정렬 |
특정 객체를 만들고나서 그 객체의 축에 다른 객체와 같은 인덱스를 붙여야할 경우가 있다.
○ reindex() 메서드를 사용하면 위의 요구조건을 충분히 충족시킬 수 있다.
○ 하지만 이러한 상황에서 reindex_like() 메서드를 사용하면 매우 쉽게 인덱스를 변경할 수 있다.
○ 다음 예제는 reindex_like()의 사용 예제를 보여준다.
reindex_like() 메서드의 사용)
# 예제용 DataFrame의 정의
In[15]: sample_df=pd.DataFrame([[1.1, 1.2, 1.3, 1.4], [2.1, 2.2, 2.3, 2.4], [3.1, 3.2, 3.3, 3.4]], index=['a', 'b', 'c'], columns=['A','B','C','D'])
In[16]: sample_df2=pd.DataFrame([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]], index=['a', 'c', 'b'], columns=['B','C','A','D'])
In[17]: sample_df
Out[17]:
A B C D
a 1.1 1.2 1.3 1.4
b 2.1 2.2 2.3 2.4
c 3.1 3.2 3.3 3.4
In[18]: sample_df2
Out[18]:
B C A D
a 0 1 2 3
c 4 5 6 7
b 8 9 10 11
# reindex_like() 메서드의 사용 예제
In[19]: sample_df.reindex_like(sample_df2)
Out[19]:
B C A D
a 1.2 1.3 1.1 1.4
c 3.2 3.3 3.1 3.4
b 2.2 2.3 2.1 2.4
reindex() 메서드 사용 시 누락값 채우기 |
다음 예제들은 reindex() 메서드를 사용하여 누락값을 채우는 예제이다.
○ 예제가 내용은 크게 없지만 길으므로 예제를 쪼개서 포스팅한다.
다음은 이 섹션에서 활용하는 예제용 DataFrame을 보여준다.
예제용 DataFrame의 정의)
# 예제용 DataFrame의 정의
In[20]: sample1=pd.DataFrame([1, 2, 3, 4, 5, 6, 7, 8, 9], index=['a', 'b', 'c', 'd', 'e', 'f','g','h','i'])
In[21]: sample2=pd.DataFrame([1, 4, 7], index=['a', 'd', 'g'])
In[22]: sample1
Out[22]:
0
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
i 9
In[23]: sample2
Out[23]:
0
a 1
d 4
g 7
다음은 reindex() 메서드를 활용하여 누락 데이터가 발생했을 시 해당 값을 채우는 예제를 보여준다.
reindex() 메서드를 사용한 누락값 채움)
# reindex() 메서드의 사용(누락값 채우지 않을 시)
In[24]: sample2.reindex(sample1.index)
Out[24]:
0
a 1.0
b NaN
c NaN
d 4.0
e NaN
f NaN
g 7.0
h NaN
i NaN
# reindex() 메서드의 사용('ffill' 옵션)
In[25]: sample2.reindex(sample1.index, method='ffill')
Out[25]:
0
a 1
b 1
c 1
d 4
e 4
f 4
g 7
h 7
i 7
# reindex() 메서드의 사용('bfill' 옵션)
In[26]: sample2.reindex(sample1.index, method='bfill')
Out[26]:
0
a 1.0
b 4.0
c 4.0
d 4.0
e 7.0
f 7.0
g 7.0
h NaN
i NaN
# 'nearest'옵션은 index를 문자열로 사용할 경우 에러 발생
# 따라서 숫자형 인덱스로 변경하여 'nearest' 옵션 적용
In[27]: sample1.index=[0, 1, 2, 3, 4, 5, 6, 7, 8]
In[29]: sample2.reindex(sample1.index, method='nearest')
Out[29]:
0
0 1
1 1
2 4
3 4
4 4
5 7
6 7
7 7
8 7
다음 예제와 같이 fillna()나 interpolate() 메서드를 사용하여 같은 방법으로도 같은 결과가 얻어질 수 있다.
○ index가 점진적으로 증가하거나 감소하지 하지 않는다면, reindex() 메서드는 ValueError를 발생시킨다.
○ fillna()나 interpolate() 메서드는 인덱스의 순서를 확인하는 절차를 수행하지 않는다.
fillna() 메서드의 사용)
# fillna() 메서드를 사용한 누락값 채우기
In[30]: sample2.reindex(sample1.index).fillna(method='ffill')
Out[30]:
0
a 1.0
b 1.0
c 1.0
d 4.0
e 4.0
f 4.0
g 7.0
h 7.0
i 7.0
reindex() 메서드 사용 시 누락값을 채우는 것에 대한 제한 |
limit나 tolerance 입력변수는 reindex를 수행할 때 값을 채우는 방법에 대한 추가적인 로직을 제공한다.
○ limit는 누락값이 연속적으로 있을때, 누락값을 채우기 위한 로직을 적용할 최대 수를 명시한다.
○ tolerance는 누락값이 연속적으로 있을 때, 누락값을 채울 인덱스와 값이 있는 인덱스의 간의 최대 거리를 명시한다.
▷ tolerance는 배열로 입력하여 각 인덱스마다 다르게 최대 거리를 명시할 수 있다.
다음은 limit 옵션을 사용하는 예제를 보여준다.
limit 옵션의 사용)
# limit 옵션의 사용
In[31]: sample2.reindex(sample1.index, method='ffill', limit=1)
Out[31]:
0
a 1.0
b 1.0
c NaN
d 4.0
e 4.0
f NaN
g 7.0
h 7.0
i NaN
다음은 tolerance 옵션을 사용하는 예제를 보여준다.
○ tolerance는 각 인덱스 값별로 거리를 명시하는 것이 가능하다.
○ DataFrameIndex, TimedeltaIndex, PeriodIndex가 사용될때, tolerance는 가능하다면 Timedelta을 사용할 것이 강제된다.
○ 이는 사용자에게 적절한 문자열을 사용하여 tolerance를 명시하도록 한다.
tolerance 옵션의 사용)
# tolerance 옵션의 사용
# index를 문자열로 사용할 경우 에러 발생
In[32]: sample1.index=[0, 1, 2, 3, 4, 5, 6, 7, 8]
drop() 메서드를 이용한 특정 레이블 데이터 제거 |
reindex와 상당히 관련있는 메서드는 drop() 메서드이다.
이 함수는 축으로부터 레이블의 집합을 제거한다.
drop() 메서드의 사용)
# 예제 DataFrame의 정의
In[36]: sample_df=pd.DataFrame([[1.1, 1.2, 1.3, 1.4], [2.1, 2.2, 2.3, 2.4], [3.1, 3.2, 3.3, 3.4]], index=['a', 'b', 'c'], columns=['A','B','C','D'])
In[36]: sample_df
Out[36]:
A B C D
a 1.1 1.2 1.3 1.4
b 2.1 2.2 2.3 2.4
c 3.1 3.2 3.3 3.4
# drop() 메서드의 사용
In[37]: sample_df.drop(['a', 'c'], axis=0)
Out[37]:
A B C D
b 2.1 2.2 2.3 2.4
In[38]: sample_df.drop(['B', 'C'], axis=1)
Out[38]:
A D
a 1.1 1.4
b 2.1 2.4
c 3.1 3.4
아래의 예제는 작동하지만 명확하지 않은 방법이다.
예제)
In[39]: sample_df.reindex(sample_df.index.difference(['a', 'd']))
Out[39]:
A B C D
b 2.1 2.2 2.3 2.4
c 3.1 3.2 3.3 3.4
.reindex()메서드 세부사항 |
Series 혹은 DataFrame가 새롭게 입력된 인덱스(index)로 변경되게 한다.
이전 인덱스에서 값을 가지지 않는 위치에는 NA/NaN을 입력한다.
copy입력변수에 False가 입력되면 새로운 객체가 생성된다.
DataFrame.reindex(**kwargs) |
keywords for axes: array-like
선택적으로 입력이 가능하다.
기존의 레이블/인덱스를 대체할 새로운 레이블/인덱스를 키워드를 사용하여 입력받는다.
데이터를 복사하는 것을 방지하기 위해 가급적 인덱스 객체를 입력하는 것이 좋다.
method: {None, ‘backfill’/’bfill’, ‘pad’/’ffill’, ‘nearest’}
이 입력변수는 인덱스가 다시 적용되는 DataFrame의 빈 자리를 채우기 위해 사용하는 변수이다.
이는 단순하게 증가하거나 감소하는 인덱스를 사용하여 DataFrame과 Series에 적용이 가능하다.
○ None: 기본값이다. 빈 공간을 채우지 않는다.
○ pad/ffill: 마지막 유효한 관측치를 다음 유효한 관측치로 전파한다.
○ backfill/ bfill: 빈 데이터를 채우기 위해, 다음 관측치를 사용한다.
○ nearest: 빈 데이터를 채우기 위해, 가장 근처에 있는 유효한 관측치를 사용한다.
copy: bool
기본값은 True이다.
만약 입력된 인덱스가 동일하더라도, 새로운 객체를 반환한다.
level: int or name
입력된 MultiIndex level의 Index 값과 일치하는 level에 걸쳐 브로드캐스팅을 수행한다.
fill_value: scalar
기본값은 np.NaN로 설정되어 있다.
누락값에 채우고자 하는 값을 입력받는다.
limit: int, default None
앞으로 또는 뒤로 채울 연속적인 요소의 최대 수를 입력받는다.
tolerance: optional
정확히 매치하지 않는 경우에 기존 레이블과 새로운 레이블 간의 최대 거리를 입력받는다.
매칭되는 위치에서의 인덱스의 값들은 abs(index[indexer] - target) <= tolerance 을 충족한다.
스칼라 값을 입력받는 경우에는 이는 모든 값들에 같은 Tolerance를 가진다.
리스트와 같은 자료형을 입력받는 경우에는 요소별로 다양하게 Tolerance를 적용할 수 있다.
○ 리스트와 같은 자료형은 list, tuple, Series, array 등을 포함한다.
○ 이 경우 반드시 인덱스와 같은 크기를 가져야한다.
○ 뿐만 아니라 dtype역시 기존인덱스와 정확히 매칭이 되어야한다.
|
|
|
| 참고자료 https://pandas.pydata.org/docs/user_guide/basics.html https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reindex.html |
|
|
|
|
'Python > Pandas' 카테고리의 다른 글
인덱스(레이블) 수정을 위한 rename() 메서드-pandas(30) (0) | 2020.09.13 |
---|---|
두 객체의 데이터 정렬을 위한 align() 메서드 - pandas(29) (0) | 2020.09.11 |
데이터셋활용 누락값 채우기, 데이터 조합-pandas(27) (0) | 2020.04.21 |
불린리덕션(empty, any, all, bool)-pandas(26) (0) | 2020.04.19 |
객체간의 비교 연산(eq, ne, lt, gt, le, ge, equals)-pandas(25) (0) | 2020.04.11 |
댓글