728x90
데이터 처리
- 판다스 객체에서 데이터 세트를 서브세트로 설정하거나 서브세트를 얻으려면 축을 라벨 처리해야 한다.
- 라벨 처리는 데이터 분석, 시각화, 양방향 디스플레이 기능에서 중요한 과정이며, 데이터를 자동 정렬하고 명시적으로 표현한다.
데이터 선택
- 데이터는 라벨(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 |