티스토리 뷰

반응형

Multi-index & Multi-column

 


#. 생성

  - 인덱스의 개수, 상위 level & 하위 level의 개수가 일치해야 함

  - 생성할 일은 많지 않음 :(


1. Series

s1 = Series([1,2,3,4,5,6], index=[['a','a','b','b','c','c'], [1,2,1,2,1,2]])

s1

a  1    1

   2    2

b  1    3

   2    4

c  1    5

   2    6

dtype: int64


2. DataFrame 생성 후 설정

df1 = DataFrame({'value':[1,2,3,4,5,6],

                       'ind1':['a','a','b','b','c','c'],

                       'ind2':[1,2,1,2,1,2]})

df1 = df1.set_index(['ind1','ind2'])  리스트 형식으로 인덱스에 동시 전달 가능

                                                 # df1.index = [df1['ind1'], df1['ind2']]  

                                                           # df1.drop(['ind1','ind2'],axis=1) 


3. DataFrame 생성과 함께 설정

df2 = DataFrame(np.arange(16).reshape(4,4),

                         index = [[1,1,2,2],['s1','s2','s1','s2']],

                         columns = [['apple','apple','banana','banana'], ['price','qty','price','qty']],

                         )



#. Series 멀티 색인

# 기본 색인 

# xs() 메서드를 활용한 색인 : axis=0 (축), level=0 (깊이) default

s1

a  1    1

   2    2

b  1    3

   2    4

c  1    5

   2    6

dtype: int64

s1.xs('a')  

s1['a']       # 상위 level key 색인

1    1

2    2

dtype: int64

s1['a':'b']   # 상위 level 슬라이스 색인

a  1    1

   2    2

b  1    3

   2    4

dtype: int64

s1[['a','c']]   # 특정 상위 level key 색인

a  1    1

   2    2

c  1    5

   2    6

dtype: int64

s1.xs(2, level=1)  

s1[:,2]   # 하위 level 색인 (이차원 색인처럼 사용

a    2

b    4

c    6

dtype: int64

s1.xs(('a',1))  

s1['a',1]   # 상위, 하위 level 색인

1

s1.xs(('b',2), level=[0,1])

b  2    4

dtype: int64





#. DataFrame 멀티 색인

# 기본 색인 

# xs() 메서드를 활용한 색인 : axis=0, level=0 (default)

   - axis=0 (row),  axis=1 (column)

   - level=0 (상위 레벨),  level = 1 (하위 레벨)

   - xs() 메서드로 column색인 시 축 설정 필요(axis가 default로 0이므로)

   - 특정 레벨 or 특정 축만 가능하고 동시 선택은 불가

df2

df2.xs('apple', axis=1) 

df2['apple']     # 컬럼색인 우선

df2['apple','price']    # 상위, 하위 level 색인

1  s1     0

   s2     4

2  s1     8

   s2    12

Name: (apple, price), dtype: int32

df2['apple','price'][1]    # 추가 색인을 통해 index를 색인 가능

s1    0

s2    4

Name: (apple, price), dtype: int32

df2.xs('apple', level = 0, axis = 1).xs(2, level=0)

   # apple 컬럼의 2번째 레벨

 



#. 계층 순서 변경 (.swaplevel)

df1 = DataFrame(np.arange(16).reshape(4,4), index=[['a','a','b','b'], [1,2,1,2]],

columns = [['col1','col1','col2','col2'], ['c1','c2','c1','c2']])

df1


df1.swaplevel?  # 계층 순서 변경

df1.swaplevel(i=-2, j=-1, axis=0)

df1.swaplevel(0,1)    # index의 계층 순서 변경

df1.swaplevel(0,1, axis=1)   # column의 계층 순서 변경




#. 컬럼의 인덱스화 (.Stack)

df1.stack?    # 컬럼의 인덱스화(그룹 연산 시 용이)

df1.stack(level=-1, dropna=True)

# dropna = False 로 옵션 지정 시, NA값 출력


df1


df1.stack()   # 하위 컬럼 인덱스화

df1.stack(level=0)   상위 컬럼 인덱스화





#. 인덱스의 컬럼화 (.unStack)

# 인덱스의 컬럼화(그룹 연산 시 용이)


df1.unstack?    

df1.unstack(level=-1, fill_value=None)

# unstack 결과, 하위 그룹에 속하지 않는 값은 NA로 처리 => fill_value 옵션으로 NA 치환


df1


df1.unstack()   하위 인덱스 컬럼화

df1.unstack(level = 0)  상위 인덱스 컬럼화





#. 연산

df1


df1.sum?

sw.sum(axis=None, skipna=None, level=None, numeric_only=None, min_count=0, **kwargs)

df1.sum(0)    # 서로 다른 행별 합

col1  c1    24

       c2    28

col2  c1    32

       c2    36

dtype: int64

df1.sum(1)   # 서로 다른 컬럼별 합

a  1     6

    2    22

b  1    38

    2    54

dtype: int64

df1.sum(0, level=0)   상위 인덱스의 합

df1.sum(1, level=0)   상위 컬럼의 합





#. Q1

### multi_index_ex1.csv 파일을 읽고 다음을 수행

data = pd.read_csv("multi_index_ex1.csv", encoding='cp949', sep=',')

data


### 1) 각 인덱스와 컬럼을 multi-index를 갖도록 설정

data = data.set_index(['지역','지역.1'])      # index 설정

data.index.names = ['품목','상세품목']       # index name 설정

 

data.columns = [data.columns.map(lambda x : x[:2]), data.iloc[0]]  # column 설정

data = data.iloc[1:]                 # set_column 메서드가 없으므로 원본에서 제거 필요

data.columns.names = ['지역','지점']    # column name 설정


data = data.astype('int')      # 데이터를 숫자형 타입으로 변환

data


### 2) 컴퓨터의 서울지역 판매량 출력

data.xs('컴퓨터').xs('서울',axis=1) 

data.loc['컴퓨터', '서울']     # 색인하려는 level이 둘 다 상위 level이므로 loc메서드로 색인 가능


### 3) 서울지역의 컴퓨터의 각 세부항목별 판매량의 합계 출력

data.loc['컴퓨터', '서울'].apply(sum, 1)

상세품목

노트북     3399

데스크탑    4730

dtype: int64


### 4) 각 지역의 A지점의 TV 판매량 출력

data.xs('A', level=1, axis=1).xs('TV', level=1)    


### 5) 각 지역 C지점의 모바일의 각 세부항목별 판매량 평균 출력

round(data.xs('C', level=1, axis=1).xs('모바일').mean(1), 2)

상세품목

핸드폰    8807.67

태블릿    1585.00

dtype: float64


### 6) 서울지역의 A지점의 노트북 판매량 출력

data['서울','A'].xs('노트북', level=1)

품목

컴퓨터    1000

Name: (서울, A), dtype: int32





#. Q2

### employment.csv 파일을 읽고

emp = pd.read_csv("employment.csv", encoding='cp949', sep=',')


emp = emp.set_index('고용형태')  # 고용형태 컬럼을 인덱스로 사용


s1 = emp.columns.map(lambda x : x[:4])

s2 = emp.iloc[0].map(lambda x : x.split(' ')[0])

emp.columns = [s1, s2]              # 컬럼 지정

emp = emp.iloc[1:]

emp.columns.names = ['년도', '구분']   # 컬럼 이름 설정


f1 = lambda x : x.replace('-','0')    # '-' 기호 치환

emp = emp.applymap(f1)

 

f2 = lambda x : x.replace(',','')     # 천 단위 구분기호 치환

emp = emp.applymap(f2)

 

emp = emp.astype('float')    # 데이터 손실을 막기 위해 정수, 실수가 합쳐진 데이터의 경우 실수(float)으로 통일

emp



### 1) 정규근로자의 월급여액을 년도별로 출력

emp.xs('월급여액', level=1, axis=1).loc['정규근로자']     # 멀티인덱스의 상위 컬럼 선택 후 인덱스 색인

년도

2007    2027.0

2008    2151.0

2009    2199.0

2010    2285.0

2011    2385.0

2012    2502.0

2013    2566.0

Name: 정규근로자, dtype: float64


### 2) 각 년도별 근로자 총근로일수의 평균 출력

emp.xs('총근로일수', level=1, axis=1).sum(axis=1)    멀티인덱스의 상위 컬럼 선택 후 서로 다른 컬럼별 연산

고용형태

전체근로자             151.5

전체근로자(특수형태포함)       0.0

정규근로자             156.1

비정규근로자            136.5

비정규근로자(특수형태포함)      0.0

특수형태근로종사자           0.0

재택/가내근로자          136.3

파견/용역근로자          143.0

일일근로자             120.8

단시간근로자            129.8

기간제근로자            150.0

한시적근로자            151.9

dtype: float64


### 3) 각 년도별 정규근로자와 비정규근로자의 월급여액의 차이 계산

emp.xs('월급여액', level=1, axis=1).loc['정규근로자'] - emp.xs('월급여액', level=1, axis=1).loc['비정규근로자'] 

년도                            키가 동일하므로 연산 가능

2007     882.0

2008     962.0

2009     997.0

2010    1066.0

2011    1103.0

2012    1189.0

2013    1194.0

dtype: float64




#. Q3

### 역별 승하차의 총 합

sub = pd.read_csv("subway2.csv", encoding='cp949', sep=',')    # skiprows=1


sub.columns = sub.iloc[0].map(lambda x : x[:2] + '')    # 첫 행을 컬럼으로 사용

sub = sub.iloc[1:]

sub.iloc[:,0] = sub.iloc[:,0].fillna(method='ffill').map(lambda x : x.split('(')[0])   # 인덱스로 사용할 첫 컬럼의 NA 치환

sub = sub.set_index(['전체시', '구분시'])   # 인덱스 설정  

                                                        # sub.set_index([sub.iloc[:,0], sub.iloc[:,1]]) => 위치기반으로 설정 시 원본 컬럼 제거 불가

sub.index.names = ['','구분']               # 익덱스 이름 설정

 

sub = sub.applymap(lambda x : int(x.replace(',','')))    # 천 단위 구분기호 제거

 

sub.sum(1).sum(level=0)

sub.sum(axis=0, level=0).sum(1)   # sum(연산 방향)

서울역     4174067

시 청     3290230

종 각     3121065

종로3     3197729

종로5가    1699115

         ...   

신용산     1119068

이 촌      599060

동 작      248554

총신대     1712004

남태령       71443

Length: 107, dtype: int64





반응형
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday