728x90
728x170
데이터 처리
- 판다스 객체에서 데이터 세트를 서브세트로 설정하거나 서브세트를 얻으려면 축을 라벨 처리해야 한다.
- 라벨 처리는 데이터 분석, 시각화, 양방향 디스플레이 기능에서 중요한 과정이며, 데이터를 자동 정렬하고 명시적으로 표현한다.
데이터 선택
- 데이터는 라벨(Label), 위치(Position), 호출(Call)을 이용해 선택할 수 있다.
① 라벨로 데이터 선택
- 라벨을 이용한 데이터 선택은 임의의 축을 따라서 범위를 나누는 일관성 있는 방법으로써 loc 속성을 사용한다.
- loc 속성에 입력할 수 있는 것들
- 1 또는 a 와 같은 단일 라벨
- ['a', 'b', 'c'] 와 같은 리스트나 라벨들의 배열
- a:f 와 같은 슬라이스 객체
- 불리언 배열
- 호출 함수
- loc 속성에 입력할 수 있는 것들
- loc 속성은 데이터의 인덱스 타입이 일치하지 않으면 오류가 발생하므로 인덱스 타입을 일치시켜야 한다.
df1 = pd.DataFrame(np.random.randn(5, 4), columns=list('ABCD'), index=pd.date_range('20210701', periods=5))
df1
df1.loc['20210702':'20210703']
df1.loc[2:3] # 오류 발생
더보기
TypeError: cannot do slice indexing on DatetimeIndex with these indexers [2] of type int
- 인덱스를 이용해 라벨을 선택하려면 모든 라벨이 인덱스에 포함되어야 하며, 그렇지 않으면 오류가 발생한다.
- 슬라이싱할 때 시작과 끝의 범위는 포함된다.
>>> ser1 = pd.Series(np.random.randn(4), index=list('abcd'))
>>> ser1
a -1.147430
b 0.058865
c -0.506377
d 0.018776
dtype: float64
>>> ser1.loc['c':]
c -0.506377
d 0.018776
dtype: float64
>>> ser1.loc['b']
0.05886489235705901
- loc 속성을 사용해 시리즈 객체에 동적 할당을 할 수 있다.
>>> ser1.loc['c':] = 0
>>> ser1
a -1.147430
b 0.058865
c 0.000000
d 0.000000
dtype: float64
- 라벨을 이용해 데이터프레임의 요소를 선택할 수 있다.
df1 = pd.DataFrame(np.random.randn(5, 4), index=list('abcde'), columns=list('ABCD'))
df1
df1.loc[['a', 'b', 'd'], :]
더보기
- df1.loc[['a', 'b', 'd'], :] 와 df1.loc[['a', 'b', 'd']] 를 입력한 후의 결과는 같다.
- 하나의 라벨과 슬라이싱을 이용해 데이터를 선택한다.
df1.loc['c':, 'A':'C']
>>> df1.loc['a']
A -1.563361
B 0.028897
C -0.919418
D -0.585012
Name: a, dtype: float64
- loc 속성을 이용해 슬라이싱을 실행할 때, 시작과 끝 라벨이 인덱스에 있다면 문자열로 인식해서 시작과 끝을 포함해 둘 사이에 위치하는 요소를 반환한다.
- 인덱스를 수치로 간주한다면 속성 iloc을 적용한다.
>>> ser = pd.Series(list('abcde'), index=[0, 3, 2, 5, 4])
>>> ser
0 a
3 b
2 c
5 d
4 e
dtype: object4
>>> ser.loc[3:5]
3 b
2 c
5 d
dtype: object
- ser.loc[1:6] 을 적용하면 2개의 라벨 요소 중 6이 인덱스 범위를 초과해 존재하지 않으므로 오류가 발생한다.
- 그러나 인덱스 라벨을 순서 정렬한 후, loc[1:6]를 적용하면 범위에 맞는 결과가 나타난다.
- 여기서 loc의 2개 라벨은 위치를 나타내는 것이 아니라 라벨 명칭인 점에 주의한다.
- 그러나 인덱스 라벨을 순서 정렬한 후, loc[1:6]를 적용하면 범위에 맞는 결과가 나타난다.
>>> ser.sort_index()
0 a
2 c
3 b
4 e
5 d
dtype: object
>>> ser.sort_index().loc[1:6]
3 b
4 e
5 d
dtype: object
② 위치로 데이터 선택
- 위치를 이용해 데이터를 선택할 때, 슬라이싱 영역의 시작은 포함되고 끝은 제외된다.
- iloc 속성으로 위치를 지정할 수 있으며, 정수, 리스트, 정수 배열을 입력으로 사용한다.
- 정수 1:5와 같은 슬라이스 객체, 불리언 배열 그리고 호출 함수를 입력할 수 있다.
>>> ser1 = pd.Series(np.random.randn(5), index=list(range(0, 10, 2)))
>>> ser1
0 -0.221171
2 -0.935806
4 -0.529686
6 -2.150953
8 0.303440
dtype: float64
>>> ser1.iloc[:3]
0 -0.221171
2 -0.935806
4 -0.529686
dtype: float64
>>> ser1.iloc[3]
-2.1509533662669043
- 데이터프레임 객체를 생성하고, 위치를 이용해 선택할 수 있다.
df1 = pd.DataFrame( np.random.randn(5, 4), index=list(range(0, 10, 2)), columns=list(range(0, 8, 2)))
df1
- 정수를 범위로 가지는 슬라이싱을 이용해 데이터를 선택한다.
- [n:m]은 위치 n부터 m-1까지의 범위이다.
df1.iloc[:2]
df1.iloc[1:3, 0:3]
- 정수 리스트를 이용해 데이터를 선택한다.
df1.iloc[[0, 2, 3], [1, 3]]
- df1 객체를 횡단으로 슬라이싱한다.
>>> df1.iloc[1]
0 0.087331
2 0.190744
4 0.487980
6 -0.596437
Name: 2, dtype: float64
③ 호출 함수로 데이터 선택
- 호출 함수(Callable)은 호출할 수 있는 함수를 의미하며, loc, iloc 및 [ ]를 이용해 인덱싱할 때 호출 함수를 인수인 인덱스 연산자로 사용할 수 있다.
- 시리즈나 데이터프레임에서 호출 함수는 하나의 인수를 가지며, 인덱싱에 합당한 출력을 반환한다.
df1 = pd.DataFrame(np.random.randn(5, 4), index=list('abcde'), columns=list('ABCD'))
df1
- 호출 함수를 인덱스 연산자로 사용하여 데이터를 선택해본다.
- df1.A 가 0보다 큰 라벨 a와 b를 행 축으로 선택하고, [:]인 모든 구간을 열 축으로 선택한다.
df1.loc[lambda df: df.A>0, :]
- 모든 행 구간을 선택하고 A와 B열을 선택한다.
df1.loc[:, lambda df: ['A', 'B']]
- 위치를 이용해 데이터를 선택하기 위해 iloc 속성을 사용할 수 있다.
df1.iloc[:, lambda df: [0, 1]]
- columns 속성을 이용해 열을 선택할 수 있다.
>>> df1[lambda df: df.columns[0]]
a -0.964580
b 0.786939
c 0.351728
d 2.155382
e 0.338592
Name: A, dtype: float64
- 시리즈에도 호출 함수 인덱스를 사용할 수 있다.
>>> df1.A.loc[lambda ser: ser > 0]
b 0.786939
c 0.351728
d 2.155382
e 0.338592
Name: A, dtype: float64
데이터 설정과 검색
- 다양한 방법으로 데이터를 설정 또는 변형하고, 필요한 데이터를 검색할 수 있다.
데이터 확장 및 변경
- 판다스의 데이터프레임이나 시리즈에 라벨을 지정하거나 슬라이싱을 실행하거나 loc, at, iat 메소드를 이용해 값을 할당하여 데이터를 확장하고 변경할 수 있다.
>>> ser = pd.Series(np.arange(3))
>>> ser
0 0
1 1
2 2
dtype: int32
>>> ser[5] = 7
>>> ser
0 0
1 1
2 2
5 7
dtype: int64
- loc를 축에 적용하면 데이터프레임을 확장할 수 있다.
df = pd.DataFrame(np.arange(9).reshape(3, 3), columns=['A', 'B', 'C'])
df
- 전체 행과 A열을 선택한 요소를 전체 행과 D열의 범위에 할당한다.
df.loc[:, 'D'] = df.loc[:, 'A']
df
- loc 를 이용하면 인덱스 라벨을 추가하고 새로운 값을 동적 할당할 수 있다.
df.loc[3] = 7
df
- 모든 데이터 구조에서 사용할 수 있는 at과 iat 메소드를 사용하면 스칼라 값에 접근할 수 있다.
- at 은 loc 와 유사하게 라벨 기반의 스칼라에 접근한다.
- iat 은 iloc 와 유사하게 정수 기반 값에 접근한다.
>>> ser.iat[3]
'd'
>>> ser.at[5]
'd'
df.at[3, 'E'] = 7
df.iat[3, 0] = 2
df
불리언 벡터로 데이터 필터링
- 데이터를 필터링할 때 불리언 벡터를 사용하는 연산을 주로 활용한다.
- 연산자 or은 |, and는 &, not은 ~로 사용한다.
>>> ser = pd.Series(range(-3, 3))
>>> ser
0 -3
1 -2
2 -1
3 0
4 1
5 2
dtype: int64
>>> ser[ser > 0]
4 1
5 2
dtype: int64
>>> ser[(ser < -1) | (ser > 1)]
0 -3
1 -2
5 2
dtype: int64
>>> ser[~(ser < 2)]
5 2
dtype: int64
- 불리언 벡터에 조건을 부여해 데이터프레임에서 행을 선택할 수 있다.
df[df['A'] < 3]
- isin() 메소드는 시리즈 전체에서 선택된 범위 요소 중, isin() 메소드의 인수로 전달된 요소가 존재하면 True, 그렇지 않으면 False를 반환한다.
- ser[::-1] 은 인덱스 라벨을 역으로 나타낸다.
>>> ser[::-1].isin([-3, -1, 2])
5 True
4 False
3 False
2 True
1 False
0 True
dtype: bool
>>> ser[ser[::-1].isin([-3, -1, 2])]
0 -3
2 -1
5 2
dtype: int64
- index 객체에도 isin() 메소드를 적용할 수 있으며, 이 메소드는 찾는 라벨이 존재하는지 알 수 없는 경우에 유용하다.
>>> ser.index.isin([2, 4, 6])
array([False, False, True, False, True, False])
>>> ser[ser.index.isin([2, 4, 6])]
2 -1
4 1
dtype: int64
- 데이터프레임에도 isin() 메소드를 사용할 수 있다.
- isin() 메소드 호출 시, 배열이나 딕셔너리 중 하나의 형태로 값들의 세트를 전달한다.
- 값이 배열이면 isin()은 원래 데이터프레임과 같은 shape인 불리언 데이터프레임을 반환한다.
df = pd.DataFrame({'no': [1, 2, 3], 'ha': ['a', 'b', 'c'], 'hi': ['m', 'n', 'o']})
val = ['a', 'n', 1, 3]
df
df.isin(val)
- 특정 열에서 값을 선택할 수도 있다.
val = {'ha': ['a', 'c'], 'no': [1, 2]}
df.isin(val)
- 데이터의 서브세트를 빠르게 선택하기 위해 데이터프레임의 isin() 메소드를 any(), all() 메소드와 조합해 사용할 수 있다.
val = {'ha': ['a', 'c'], 'hi': ['m', 'o'], 'no': [1, 2]}
mask = df.isin(val).all(1)
df[mask]
take() 메소드로 검색
- 판다스의 인덱스, 시리즈 및 데이터프레임은 인덱스에서 축에 따른 요소를 검색하는 take() 메소드를 제공한다.
- 이때 인덱스는 리스트 혹은 정수 인덱스 위치의 ndarray 이어야 한다.
>>> index = pd.Index(np.random.randint(0, 1000, 6))
>>> index
Int64Index([702, 485, 470, 493, 220, 442], dtype='int64')
>>> positions = [0, 2, 5]
>>> index[positions]
Int64Index([702, 470, 442], dtype='int64')
>>> index.take(positions)
Int64Index([702, 470, 442], dtype='int64')
>>> ser = pd.Series(np.random.randn(10))
>>> ser.iloc[positions]
0 -1.800911
2 1.351300
5 1.461708
dtype: float64
>>> ser.take(positions)
0 -1.800911
2 1.351300
5 1.461708
dtype: float64
df = pd.DataFrame(np.random.randn(5, 3))
df.take([1, 4, 3])
df.take([0, 2], axis=1)
손실 데이터 처리
- 판다스를 통해 손실 데이터를 매우 유연하게 처리할 수 있다.
d = {'one': [1.5, 2.2, -3.0], 'two': [1.0, -1.2, 5.0], 'three': [-1.1, 2.0, 4.0]}
df = pd.DataFrame(d, index = ['a', 'c', 'f'])
df['four'] = 'ha'
df['five'] = df['one'] > 0
df
- reindex() 메소드를 사용하여 존재하지 않는 요솟값 NaN을 갖도록 df에 새로운 인덱스를 추가하였다.
df1 = df.reindex(['a', 'b', 'c', 'd', 'e', 'f'])
df1
- 판다스는 손실 값을 쉽게 탐지할 수 있도록 시리즈와 데이터프레임의 isna()와 notna() 메소드를 제공한다.
>>> df1['one']
a 1.5
b NaN
c 2.2
d NaN
e NaN
f -3.0
Name: one, dtype: float64
>>> pd.isna(df1['one'])
a False
b True
c False
d True
e True
f False
Name: one, dtype: bool
>>> df1['four'].notna()
a True
b False
c True
d False
e False
f True
Name: four, dtype: bool
- 파이썬의 None과 None은 서로 같지만, 넘파이의 nan과 nan은 서로 다르다는 점에 주의한다.
>>> None == None
True
>>> np.nan == np.nan
False
손실 데이터 계산
- 판다스 객체들을 산술 연산할 때 손실 값들은 브로드캐스팅되어 연산된다.
d1 = {'one': [1.0, 2.0, 3.0], 'two': [4.0, 5.0, 6.0]}
df1 = pd.DataFrame(d1, index = ['a', 'b', 'c'])
df2 = df1.copy()
df2.loc['d'] = np.nan
df2['three'] = 2.0
df2.iloc[1:2, 1:2] = np.nan
df1
df2
df1 + df2
- 값이 비어 있거나 모두 NA인 시리즈의 합은 0이고, 곱은 1이다.
>>> pd.Series([np.nan]).sum()
0.0
>>> pd.Series([], dtype=object).sum()
0
>>> pd.Series([np.nan]).prod()
1.0
>>> pd.Series([], dtype=object).prod()
1
- GroupBy 에서 NA는 자동으로 제외된다.
df2
df2.groupby('two').mean()
손실 데이터 채우기
- 판다스는 손실 데이터를 처리하는 다양한 방법을 제공한다.
- fillna() 메소드를 이용해 NA를 스칼라 값으로 대체할 수 있다.
df2.fillna(0)
>>> df2['one'].fillna('missing')
a 1
b 2
c 3
d missing
Name: one, dtype: object
- method='pad'를 이용해 손실 값을 앞 데이터의 값으로 채울 수 있다.
df2
df2.fillna(method='pad')
- fillna() 메소드에 판다스 객체를 인수로 입력해 손실 값을 채울 수 있다.
- 딕셔너리의 라벨이나 시리즈의 인덱스는 채우고자 하는 프레임의 열에 맞춰야 한다.
df2.loc['c', 'three'] = np.nan
df2
>>> df2.mean()
one 2.0
two 5.0
three 2.0
dtype: float64
df2.fillna(df2.mean())
- fillna() 메소드를 적용하기 위해 먼저 데이터프레임 객체를 다음과 같이 생성한다.
df = pd.DataFrame([ [np.nan, 2, 0, np.nan], [3, 4, np.nan, 1], [np.nan, 5, np.nan, 2],
[np.nan, 1, 2, 3]], columns=list('ABCD'))
df
- 모든 손실 값을 0으로 대체한다.
- 파이썬은 NaN을 실수로 인식하여 0이 아닌 0.0으로 표현하고, B열은 정수로 표현한다.
df.fillna(0)
- non-null 값들을 앞이나 뒤로 브로드캐스팅할 수 있다.
df.fillna(method='ffill')
- 다음과 같이 열 'A', 'B', 'C', 'D'에 있는 모든 손실 값을 각각 0, 1, 2 그리고 3으로 대체할 수 있다.
val = {'A': 0, 'B': 1, 'C': 2, 'D': 3}
df.fillna(value=val)
- 다음과 같이 val 을 기준으로 손실 값을 대체할 수 있다.
- limit=1은 열을 기준으로 첫 번째 손실 값만 대체하라는 의미이다.
df.fillna(value=val, limit=1)
- 데이터 세트에서 손실 데이터를 갖는 라벨을 제외하려면 drop() 메소드를 사용한다.
df2.iloc[2:3, 2:3] = 2.0
df2
df2.dropna(axis=0)
df2.dropna(axis=1)
>>> df2['two'].dropna()
a 4.0
c 6.0
Name: two, dtype: float64
- 다음은 데이터 타입이 datetime64[ns]인 경우 손실 값을 NaT인 요소로 나타내는 df 객체를 생성한다.
df = pd.DataFrame({'name': ['haena', 'suho', 'naeun'], 'hobby': ['jogging', 'reading', np.nan],
'born': [pd.NaT, pd.Timestamp('2001-01-01'), pd.NaT]})
df
- 앞 데이터프레임에서 최소한 1개 요소에 손실 값이 있는 행 또는 열을 제거한다.
df.dropna()
df.dropna(axis='columns')
- 다음에서 모든 요소가 손실 값을 가지는 행을 제거하는 옵션을 적용했지만, 해당 사항이 없어 행이 변경되지 않았다.
df.dropna(how='all')
- 이번에는 최소한 2개의 손실 값이 있는 행을 제거한다.
df.dropna(thresh=2)
- 옵션에 해당하는 열에 손실 값이 있는 행을 제거한다.
df.dropna(subset=['name', 'born'])
df.dropna(subset=['hobby'])
- dropna()에 inplace=True 옵션을 입력하면 제거한 손실 값을 반영한 사항을 바로 저장한다.
df.dropna(inplace=True)
df
- 지금까지 손실 값을 대체하기 위해 fillna() 메소드를 사용하였지만, replace() 메소드를 이용해 간단하면서 유연하게 손실 값을 처리할 수도 있다.
>>> ser = pd.Series([0, np.nan, 2, 3, 5])
>>> ser
0 0.0
1 NaN
2 2.0
3 3.0
4 5.0
dtype: float64
>>> ser.replace(np.nan, 1.0)
0 0.0
1 1.0
2 2.0
3 3.0
4 5.0
dtype: float64
- replace() 메소드는 ser 객체의 요소를 대체할 수 있지만, 원래 ser 객체의 요소를 변경할 수는 없다.
- 뷰와 복사의 차이점과 유사하다.
>>> ser.replace({np.nan: 1, 5: 4})
0 0.0
1 1.0
2 2.0
3 3.0
4 4.0
dtype: float64
- 여러 요소를 하나의 값으로 대체하려면 리스트를 사용한다.
- 또한, 리스트를 사용해 해당 요소들을 각각 다른 값으로 대체할 수도 있다.
>>> ser.replace([0, 2], 1)
0 1.0
1 NaN
2 1.0
3 3.0
4 5.0
dtype: float64
>>> ser.replace([np.nan, 5], [1, np.nan])
0 0.0
1 1.0
2 2.0
3 3.0
4 NaN
dtype: float64
- 데이터프레임의 손실 값을 대체할 때는 열을 기준으로 개별 값을 딕셔너리형으로 입력하고 대체하려는 값을 입력한다.
df = pd.DataFrame({'A': [0, 1, np.nan], 'B': [3, 4, 5]})
df.replace({'A': np.nan, 'B': 3}, 10)
멀티 인덱스(Multi Index)
- 계층적 인덱스라고도 불린다.
- 하나의 축에 둘 이상의 인덱스를 지정할 수 있도록 한다.
- 멀티 인덱싱은 고차원 데이터 행에 대해 열이 여러 인덱스 라벨을 가지는 구조이다.
- 멀티 인덱싱은 고차원 데이터를 1차원인 시리즈나 데이터프레임 같은 저차원 데이터 구조로 저장하고 관리를 할 수 있게 한다.
- 멀티 인덱싱을 이용하면 그룹화, 선택 및 재형성 연산을 할 수 있다.
- 또한, 파일에서 데이터를 읽어 데이터 세트를 준비할 때 원하는 멀티인덱스를 생성할 수 있다.
멀티 인덱스 객체 생성
- 판다스 객체에서는 다음과 같은 방법으로 축의 멀티 인덱스를 생성한다.
- MultiIndex.from_array() 를 사용하는 배열 리스트
- MultiIndex.from_tuples() 를 사용하는 튜플 배열
- MultiIndex.from_product() 를 사용하는 고차 세트의 이터러블
- MultiIndex.from_frame() 을 사용하는 데이터프레임
- 인덱스 연산자가 튜플 리스트를 전달 받으면 멀티 인덱스를 반환한다.
>>> li = [['ha', 'ha', 'hi', 'hi', 'ho', 'ho'], ['one', 'two', 'one', 'two', 'one', 'two']]
>>> li1 = list(zip(*li))
>>> li1
[('ha', 'one'),
('ha', 'two'),
('hi', 'one'),
('hi', 'two'),
('ho', 'one'),
('ho', 'two')]
- MultiIndex 클래스의 from_tuples() 메소드를 이용해 멀티 인덱스 객체를 인수로 하는 시리즈 객체를 생성한다.
>>> ind = pd.MultiIndex.from_tuples(li1, names=['1st', '2nd'])
>>> ind
MultiIndex([('ha', 'one'),
('ha', 'two'),
('hi', 'one'),
('hi', 'two'),
('ho', 'one'),
('ho', 'two')],
names=['1st', '2nd'])
>>> ser = pd.Series(np.random.randn(6), index=ind)
>>> ser
1st 2nd
ha one -0.339264
two -0.615008
hi one -0.269377
two 0.187064
ho one -0.652559
two 0.178951
dtype: float64
- MultiIndex.from_product()를 이용해 2개의 이터러블을 짝지으면 객체를 더 쉽게 생성할 수 있다.
>>> iter = [['ha', 'hi', 'ho'], ['one', 'two']]
>>> pd.MultiIndex.from_product(iter, names=['1st', '2nd'])
MultiIndex([('ha', 'one'),
('ha', 'two'),
('hi', 'one'),
('hi', 'two'),
('ho', 'one'),
('ho', 'two')],
names=['1st', '2nd'])
- MultiIndex.from_frame() 메소드를 이용하면 데이터프레임에서 직접 멀티 인덱스 객체를 구성할 수 있다.
- 이 메소드는 판다스 라이브러리 0.24.0 버전부터 새로 추가되었으므로, 이전 버전에서는 오류가 발생할 수 있다.
>>> df = pd.DataFrame([['ha', 'one'], ['ha', 'two'], ['ho', 'one'], ['ho', 'two']], columns=['1st', '2nd'])
>>> pd.MultiIndex.from_frame(df)
MultiIndex([('ha', 'one'),
('ha', 'two'),
('ho', 'one'),
('ho', 'two')],
names=['1st', '2nd'])
- 배열 리스트를 직접 시리즈나 데이터프레임에 입력하면 멀티 인덱스를 자동으로 생성할 수 있다.
>>> arr = [ np.array(['ha', 'ha', 'hi', 'hi', 'ho', 'ho']), np.array(['one', 'two', 'one', 'two', 'one', 'two'])]
>>> ser = pd.Series(np.random.randn(6), index=arr)
>>> ser
ha one 1.338737
two 1.077762
hi one 1.539513
two -0.106579
ho one -1.090840
two 0.370244
dtype: float64
df = pd.DataFrame(np.random.randn(6, 3), index=arr)
df
- 판다스 객체의 행 또는 열 축에 인덱스를 적용할 수 있고, 인덱스 레벨 수는 필요한 만큼 지정할 수 있다.
df = pd.DataFrame(np.random.randn(3, 6), index=['A', 'B', 'C'], columns=ind)
df
멀티 인덱스 인덱싱
- 멀티 인덱스 인덱싱의 주요 특징 중 하나는 데이터 세트에서 서브그룹을 지정하는 인덱스 라벨로 서브 그룹을 생성할 수 있다는 것이다.
df['ha']
>>> df['ha']['one']
A 1.588027
B -2.613225
C -1.317432
Name: one, dtype: float64
- 시리즈와 데이터프레임의 reindex() 메소드는 다른 멀티 인덱스, 리스트 또는 튜플 배열과 함께 호출할 수 있다.
>>> ser.reindex(ind[:3])
1st 2nd
ha one 1.338737
two 1.077762
hi one 1.539513
dtype: float64
>>> ser.reindex([('ho', 'one'), ('ha', 'two')])
ho one -1.090840
ha two 1.077762
dtype: float64
- loc 속성에 멀티 인덱스를 적용하여 인덱싱 할 수 있으며, 이때 키는 튜플 형태이다.
df = df.T
df
>>> df.loc[('ha', 'two')]
A -1.258368
B -1.097652
C 0.636064
Name: (ha, two), dtype: float64
- loc 속성을 이용해 특정 열을 인덱싱할 수 있다.
>>> df.loc[('ha', 'two'), 'A']
2.2929073915855724
df.loc['ha']
- df 객체를 부분 슬라이싱할 수 있다.
df.loc['ha':'hi']
- 범위를 튜플 형태로 지정해 데이터를 슬라이싱 할 수 있다.
df.loc[('hi', 'two'):('ho', 'one')]
df.loc[('hi', 'two'):'ho']
- loc 속성에 라벨이나 튜플의 리스트를 전달하면 인덱스 재배열처럼 작용한다.
df.loc[[('ha', 'two'), ('ho', 'one')]]
멀티 인덱스 순서 정렬
- 효과적인 슬라이싱과 인덱싱을 위해 멀티 인덱스 처리된 객체의 순서를 정렬해야 한다.
- 먼저 shuffle() 함수를 사용해 li1 객체의 요소들을 섞는다.
>>> li1
[('ha', 'one'),
('ha', 'two'),
('hi', 'one'),
('hi', 'two'),
('ho', 'one'),
('ho', 'two')]
>>> np.random.shuffle(li1)
>>> li1
[('ho', 'one'),
('ha', 'two'),
('ho', 'two'),
('hi', 'one'),
('ha', 'one'),
('hi', 'two')]
- sort_index() 메소드를 사용해 멀티 인덱스 순서에 맞춰 정렬한다.
>>> ser = pd.Series(np.random.randn(6), index=pd.MultiIndex.from_tuples(li1))
>>> ser
ho one 1.249362
ha two 0.409203
ho two 1.100604
hi one -0.441275
ha one 0.384636
hi two 2.083151
dtype: float64
>>> ser.sort_index()
ha one 0.384636
two 0.409203
hi one -0.441275
two 2.083151
ho one 1.249362
two 1.100604
dtype: float64
>>> ser.sort_index(level=0)
ha one 0.384636
two 0.409203
hi one -0.441275
two 2.083151
ho one 1.249362
two 1.100604
dtype: float64
>>> ser.sort_index(level=1)
ha one 0.384636
hi one -0.441275
ho one 1.249362
ha two 0.409203
hi two 2.083151
ho two 1.100604
dtype: float64
- set_names() 메소드를 사용하면 멀티 인덱스 레벨에 이름을 설정할 수 있다.
- sort_index() 메소드에 level 인수를 사용하면 인덱스 레벨 이름의 순서를 정렬할 수 있다.
>>> ser.index.set_names(['1st', '2nd'], inplace=True)
>>> ser.sort_index(level='1st')
1st 2nd
ha one 0.384636
two 0.409203
hi one -0.441275
two 2.083151
ho one 1.249362
two 1.100604
dtype: float64
>>> ser.sort_index(level='2nd')
1st 2nd
ha one 0.384636
hi one -0.441275
ho one 1.249362
ha two 0.409203
hi two 2.083151
ho two 1.100604
dtype: float64
- 고차원 객체가 멀티 인덱스를 가지면 level 인수로 특정 축을 정렬할 수 있다.
df
df.T.sort_index(level=1, axis=1)
728x90
그리드형(광고전용)
'In-depth Study > Pandas' 카테고리의 다른 글
[Pandas] 수학 계산 (0) | 2022.05.31 |
---|---|
[Pandas] 데이터의 그룹 연산 (0) | 2022.05.30 |
[Pandas] 데이터 가공 (0) | 2022.05.29 |
[Pandas] 데이터 타입과 입출력 (0) | 2022.05.27 |
[Pandas] 판다스의 주요 기능 (0) | 2022.05.25 |
[Pandas] 판다스 데이터 구조 (1) | 2022.05.24 |
[Pandas] 판다스(Pandas) 개요 (0) | 2022.05.24 |