분석을 하다 보면 원본 데이터의 구조가 분석 기법에 맞지 않아서 행과 열의 위치를 바꾼다거나, 특정 요인에 따라 집계를 해서 구조를 바꿔주어야 하는 경우가 있습니다.

 

재구조화(reshaping data)를 위해 사용할 수 있는 Python pandas의 함수들로 아래와 같이 다양한 함수가 있습니다. 

 

 - (1) pivot(), pd.pivot_table()

 - (2) stack(), unstack()

 - (3) melt()

 - (4) wide_to_long()

 - (5) pd.crosstab() 

 

 

이번 포스팅에서는 마지막으로 범주형 변수로 되어있는 요인(factors)별로 교차분석(cross tabulations) 해서, 행, 열 요인 기준 별로 빈도를 세어서 도수분포표(frequency table), 교차표(contingency table) 를 만들어주는 pd.crosstab() 에 대해서 알아보겠습니다.

 

 

 

 

 

먼저 필요한 모듈을 불러오고, 예제로 사용할 (범주형 요인 변수를 가지고 있는) 간단한 데이터셋을 생성해보겠습니다.

 

 

In [1]: import pandas as pd


In [2]: from pandas import DataFrame


In [3]: data = DataFrame({'id': ['id1', 'id1', 'id1', 'id2', 'id2', 'id3'],

   ...: 'fac_1': ['a', 'a', 'a', 'b', 'b', 'b'],

   ...: 'fac_2': ['d', 'd', 'd', 'c', 'c', 'd']})


In [4]: data

Out[4]:

    fac_1   fac_2    id
0     a       d       id1
1     a       d       id1
2     a       d       id1
3     b       c       id2
4     b       c       id2
5     b       d       id3

 

 

 

 

  (1) 교차표(contingency table, frequency table) 만들기 : pd.crosstab(index, columns)

 

pd.crosstab()의 행과 열 위치에는 array 형식의 데이터가 들어갑니다

 

 

# cross tabulations using pd.crosstab => contingency table

In [5]: pd.crosstab(data.fac_1, data.fac_2)

Out[5]:
fac_2  c  d
fac_1     
a      0  3
b      2  1

 

In [6]: pd.crosstab(data.id, data.fac_1)

Out[6]: 
fac_1  a  b
id        
id1    3  0
id2    0  2
id3    0  1

 

In [7]: pd.crosstab(data.id, data.fac_2)

Out[7]:
fac_2  c  d
id        
id1    0  3
id2    2  0
id3    0  1

 

 

 

 

  (2) Multi-index, Multi-level로 교차표 만들기 : pd.crosstab([id1, id2], [col1, col2])

 

 

# cross tabulations using pd.crosstab with Multi-level columns

In [8]: pd.crosstab(data.id, [data.fac_1, data.fac_2])

Out[8]:

fac_1  a  b  
fac_2  d  c  d
id           
id1    3  0  0
id2    0  2  0
id3    0  0  1


In [9]: pd.crosstab([data.fac_1, data.fac_2], data.id)

Out[9]:

id           id1  id2  id3
fac_1 fac_2              
a     d        3    0    0
b     c        0    2    0
      d        0    0    1

 

 

 

 

  (3) 교차표의 행 이름, 열 이름 부여 : pd.crosstab(rownames=['xx'], colnames=['aa'])

 

 

# pd.crosstab(rownames, colnames) : giving rownames, colnames

In [10]: pd.crosstab(data.id, [data.fac_1, data.fac_2],

    ...: rownames=['id_num'],

    ...: colnames=['a_b', 'c_d'])

Out[10]:

a_b     a  b  
c_d     d  c  d
id_num        
id1     3  0  0
id2     0  2  0
id3     0  0  1

 

 

 

 

  (4) 교차표의 행 합, 열 합 추가하기 : pd.crosstab(margins=True)

 

 

# pd.crosstab(margins=True) : adding row/column margins

In [11]: pd.crosstab(data.id, [data.fac_1, data.fac_2],

    ...: margins=True)

Out[11]:

fac_1  a  b    All
fac_2  d  c  d   
id               
id1    3  0  0   3
id2    0  2  0   2
id3    0  0  1   1
All    3  2  1   6

 

 

 

 

 

  (5) 구성비율로 교차표 만들기 : pd.crosstab(normalize=True)

 

# pd.corsstab(normalize=True)
# : Normalize by dividing all values by the sum of values

In [12]: pd.crosstab(data.id, [data.fac_1, data.fac_2],

    ...: normalize=True)

Out[12]:

fac_1    a         b         
fac_2    d         c         d
id                           
id1    0.5  0.000000  0.000000
id2    0.0  0.333333  0.000000
id3    0.0  0.000000  0.166667

 

 

 

 

이상으로 pd.crosstab() 을 이용한 교차표 구하기를 마치겠습니다. 

 

 

교차표는 R이나 SPSS가 깔끔하게 결과를 제시해주는 것 같고요, R이 분석가가 설정할 수 있는 옵션이 조금 더 다양하므로 입맛에 맞게 교차분석도 하고 카이제곱검정도 하고 싶은 분은 아래 링크되어 있는 포스팅을 참고하세요. 

 

 

 

많은 도움이 되었기를 바랍니다.  

 

 

Posted by R Friend R_Friend

댓글을 달아 주세요

분석을 하다 보면 원본 데이터의 구조가 분석 기법에 맞지 않아서 행과 열의 위치를 바꾼다거나, 특정 요인에 따라 집계를 해서 구조를 바꿔주어야 하는 경우가 있습니다.

 

재구조화(reshaping data)를 위해 사용할 수 있는 Python pandas의 함수들에 대해서 아래의 순서대로 나누어서 소개해보겠습니다.

 

 - (1) pivot(), pd.pivot_table()

 - (2) stack(), unstack()

 - (3) melt()

 - (4) wide_to_long()

 - (5) pd.crosstab() 

 

 

이번 포스팅에서는 pd.wide_to_long() 에 대해서 알아보겠습니다.

 

필요한 모듈을 불러오고, 실습에 필요한 간단한 예제 데이터셋을 만들어보겠습니다.

 

 

# importing libraries

In [1]: import numpy as np


In [2]: import pandas as pd


In [3]: from pandas import DataFrame


# setting random seed number

In [4]: np.random.seed(10)


# making an example 'wide' DataFrame

In [5]: data_wide = pd.DataFrame({"C1prd1" : {0 : "a", 1 : "b", 2 : "c"},

   ...: "C1prd2" : {0 : "d", 1 : "e", 2 : "f"},

   ...: "C2prd1" : {0 : 2.5, 1 : 1.2, 2 : .7},

   ...: "C2prd2" : {0 : 3.2, 1 : 1.3, 2 : .1},

   ...: "value" : dict(zip(range(3), np.random.randn(3)))

   ...: })

   ...:


In [6]: data_wide["seq_no"] = data_wide.index


In [7]: data_wide

Out[7]:

     C1prd1 C1prd2  C2prd1  C2prd2     value      seq_no
0       a         d         2.5       3.2      1.331587       0
1       b         e         1.2       1.3      0.715279       1
2       c          f         0.7       0.1     -1.545400       2

 

 

 

 

이제 pd.wide_to_long() 함수를 써서 데이터를 재구조화 해보겠습니다.

 

wide_to_long()은 pivot() 이나 stack() 과는 다르게 "칼럼 이름의 앞부분"과 나머지 "칼럼 이름의 뒷부분"을 구분해서, 칼럼 이름의 앞부분을 칼럼 이름으로, 칼럼 이름의 나머지 뒷부분을 행(row)의 원소로 해서 세로로 길게(long~) 쌓아 줍니다.  말로 설명해주기가 참 힘든데요, 아래의 wide_to_long() 적용 전, 후의 변화 이미지를 참고하시기 바랍니다.

 

제가 R, SAS, SPSS 다 써봤는데요, Python의 pd.wide_to_long() 함수 같은거는 본 적이 없습니다. 좀 생소하고, 처음 봤을 때 한눈에 잘 안들어왔던 유형의 데이터 재구조화 함수예요. 

 

 

 

pd.widt_to_long() 함수를 한번 사용해서 가로로 넓은 데이터(wide~)를 세로로 길게(long~) 재구조화 해보겠습니다.

 

 

  (1) pd.wide_to_long(data, ["col_prefix_1", "col_prefix_2"], i="idx_1", j="idx_2")

 

 

# reshaping a 'wide' DataFrame to a 'long' DataFrame

In [8]: data_long = pd.wide_to_long(data_wide, ["C1", "C2"], i="seq_no", j="prd")


In [9]: data_long

Out[9]:

                     value    C1    C2
seq_no prd                 
0        prd1  1.331587      2.5
1        prd1  0.715279   b     1.2
2        prd1 -1.545400   c     0.7
0        prd2  1.331587      3.2
1        prd2  0.715279   e     1.3
2        prd2 -1.545400   f     0.1

 

 

 

 

  (2) pd.wide_to_long()에 의한 index, columns 변화 비교

 

 

# data_wide (original data set) : index, columns

In [10]: data_wide.index

Out[10]: Int64Index([0, 1, 2], dtype='int64')


In [11]: data_wide.columns

Out[11]: Index(['C1prd1', 'C1prd2', 'C2prd1', 'C2prd2', 'value', 'seq_no'], dtype='object')

 


# data_long (reshaped data set) : index, columns

In [12]: data_long.index

Out[12]:

MultiIndex(levels=[[0, 1, 2], ['prd1', 'prd2']],

labels=[[0, 1, 2, 0, 1, 2], [0, 0, 0, 1, 1, 1]],

names=['seq_no', 'type'])


In [13]: data_long.columns

Out[13]: Index(['value', 'C1', 'C2'], dtype='object')

 

 

 

이상으로 pd.wide_to_long() 을 이용한 데이터 재구조화 소개를 마치겠습니다.

 

다음번 포스팅에서는 pd.crosstab() 에 대해서 알아보겠습니다.

 

많은 도움 되었기를 바랍니다.

 

 

Posted by R Friend R_Friend

댓글을 달아 주세요