본문 바로가기
크로스집계표(cross tabulation) VS 피봇테이블(pivot)의 속사정

이번에는 pivot table, cross tabulation(교차 빈도 집계표, contingency table)에 대한 이야기. 교차분석을 하기 전에 필요한 이야기를 하려고 합니다. 보통 cross tabulation을 pivot의 특수한 형태라고 용어를 정의하는데, 정의가 맞긴 한데, pandas에서 이 두 개의 정의를 파괴하는 바람에 조금 헷갈리기 시작하는데, 그것을 짚고 넘어가려고 합니다. 

이번에는 이례적으로 pandas기능을 직접적으로 같이 써 볼까 하는데 괜찮겠죠. cross table(contingency table)은 빈도에 관련한 교차표입니다. 빈도가 얼마나 되는지 결과로 만들기 매우 편리하죠. 무엇을 교차하느냐 하면, 데이터의 2개 컬럼을 교차합니다. 

일단, 범주형 자료에 대해서 빈도를 분석한다고 생각하면 되는데, 일단 이런 교차집계표를 만들 수 있다면, 이미 검정에서 살펴본 독립성(연관성), 동질성 검정이 가능합니다. 오호.

이런 식의  데이터가 있다고 합시다. 이때, cross table은 어떤 것이냐면, 두 개의 컬럼을 교차해서 만드는데,

이런 식으로 범주형 데이터의 개수를 세어서 보는 것 입니다.가만히 보면 9월 3일 11am 수박이 2개 있고요, 나머지는 1개씩 있는 모양이군요. - 당도가 다르긴 하지만요 -

가장 중요한 이해하기 쉬운 방법을 먼저 이야기 하자면,  cross table은 Grouping and Agggregation입니다. 그러니까, row와 column을 Grouping을 한 후에 그에 대한 집계를 한다고 보면 가장 쉽게 이해하는 방법입니다. 그러니까 사과, 수박, 오렌지가 아무리 많이 나와도 이 세 가지로 Grouping이 가능하고, 출하일은 9월 1일, 9월 2일, 9월 3일로 모두 Grouping 해서 몰아넣을 수 있습니다. 

그러면, 이 cross tabulation은 어떻게 만드느냐 하면 pandas의 crosstab을 이용하면 간단하게 만들 수 있습니다. 헤헤.

pd.crosstab(df_data['과일'], df_data['출하일'])

 

그러니까 이 결과는 과일의 unique value들 (Grouping)과 출하일의 unique value만(Grouping)을 index와 column으로 만들어서 그 수를 count(Aggregation)하는 결과입니다. 교차표(cross tabulation)를 만드는 작업은 엄청 간단합니다. 여기에서 데이터를 어떻게 넣느냐면 index와 column에 데이터를 Series 형태로 "직접" 집어넣습니다. 그러니까 list나 뭐 이런 것에 들어 있는 데이터를 직접 넣어만 준다면 가능하겠죠. 이것을 지금은 주의해서 기억해 주세요.

음. 그러면 우리가 흔히 엑셀에서 봐 왔던 pivot은 cross tabulation과 어떻게 다른가 보면, 보통 cross tabulation이 pivot의 특수한 형태라고 하는데, 그 이유가 원래는 cross tabulation은 데이터의 개수를 count하는데 쓰고, pivot은 여러 가지 집계를 하는데 써서 그러는데, 그건 그냥 용어상 일반적인 차이를 이야기하는 것이지 pandas의 cross tabulation과 pivot은 하는 일이 똑같습니다. pandas의 pivot은 raw data가 pandas의 Dataframe이어야 한다는 점이 다른 점입니다. 

cross tabulation을 만들어 봤던 것을 pivot으로 하게 된다면 다음과 같이 하게 됩니다.

pd.pivot_table(df_data, index='과일', columns='출하일', aggfunc='size')

 

이렇게 하면 똑같은 결과가 나옵니다. 가만히 보면 pivot은 pandas dataframe을 통째로 데이터로 넣은 다음에 그중에 index와 column이 무엇인지 정해주면 됩니다. 자, 그럼 pivot을 이용해서 집계를 할 수 있는데, 과일별 - 출하일에 대해서 당도의 (각각의 Grouping) 평균(Aggregation)을 보고 싶다고 한다면 

데이터 개수를 count를 하는 대신에, count자리에 다른 column값을 넣을 수 있습니다. 

pd.pivot_table(df_data, index='과일', columns='출하일', values='당도')

 

오, 그렇군요. 이런 식으로 빈도 이외에 다른 데이터를 집계 할 수 있습니다. 집계 함수에 다른 방법을 정의하면 되는데요. 이런 식으로 데이터를 여러 가지 형태로 합치거나 평균을 내서 볼 수 있는데, 이것을 흔히 pivot 테이블이라고 합니다. 

하지만, pandas에서만큼은 cross_tab도 pivot과 같은 집계를 낼 수 있다는 점을 알면 좋겠습니다. 뭐 이건 cross tabulation/ pivot의 용어와 별개로 pandas가 지원한다는 의미입니다. 한 가지만 예를 든다면, 

pd.crosstab(index=df_raw['과일'], columns=df_raw['출하일'], values=df_raw['당도'], aggfunc=np.sum)

 

이런 식으로 pivot과 똑같은 효과를 낼 수 있습니다. 

pandas에는 pivot과 pivot_table 두가지를 제공하는데, 차이는 pivot은 중복된 index와 column을 처리하지 못하는데, pivot_table은 처리할 수 있습니다. - 즉 Grouping을 할 수 있습니다. - 호출하는 방법도 다른데, pivot은 dataframe.pivot(index, columns, values)로 사용하고, pivot table은 pd.pivot_table(index, columns, values)로 사용합니다. 보통은 pd.pivot_table이 더 유연하기 때문에 더 많이 사용합니다. 

pivot table을 만들 때 aggfunc (집계함수)가 무엇인지 아무것도 주지 않으면 기본적으로 평균을 계산합니다. 

사실 복잡한 이야기가 될까봐 하지 않은 이야기가 있는데, 교차표를 만들 때 index와 column 모두 multi index, multi column으로 만들 수 있습니다. 

보통 교차표를 통해서 빈도(비율)분석을 자세히 하는 경우가 많고요, 그런 경우에는 교차표에서 행을 독립변수, 열을 종속변수로 두면 읽기 편합니다. - 사실 느꼈겠지만, 지금까지 그렇게 했습니다. - 그러니까, 예를 들어 OO에 따른 XX의 차이를 알고 싶다고 하면, OO을 행으로 두고 독립변수이고요, XX가 열로 두고 종속변수로 둔다는 식입니다.

그렇게 한 경우라면 교차표에서 행을 기준으로 행의 합계를 100%로 생각하고, 독립변수 기준으로 빈도의 결과를 비율로 읽으면 감이 잘 옵니다.

짧은 예로 χ²검정에서 보았던 교차표는 예를 든다면

마심, 안마심을 기준으로 마시는 사람 100%, 56명에 대해서 피움이 85.7%, 안 피움이 14.3%, 안마시는 사람 100%, 44명에 대해서 피움이 20.4%, 안 피움이 79.6%라고 표기한다면 각 그룹에 대해 감이 확연하게 빨리 오겠지요? pie 차트 등을 이용해서도 금방 시각화가 가능합니다. 검정에서 봤던 이 교차표를 기억할지 모르겠지만 χ²검정 결과는 술과 담배는 서로 독립하지 않았었습니다.

- 물론 반대로 컬럼을 독립변수로 생각하는 것이 편하다면 그렇게 해도 됩니다 -

친절한 데이터 사이언스 강좌 글 전체 목차 (정주행 링크) -



댓글





친절한 데이터 사이언스 강좌 글 전체 목차 (정주행 링크) -