2017-12-28 6 views
3

여러 가지 범주 형 변수가 포함 된 팬더 데이터 프레임이 있습니다. 예를 들면 :개수 및 비율이 포함 된 범주 형 변수의 판별 데이터 프레임을 MultiIndex로 변환

import pandas as pd 

d = {'grade':['A','B','C','A','B'], 
    'year':['2013','2013','2013','2012','2012']} 

df = pd.DataFrame(d) 

enter image description here

나는 다음과 같은 속성을 가진 MultiIndex DataFrame이 변환하고자하는

:

  • 첫번째 레벨 인덱스 변수 이름 (예를 들어 '등급')
  • 입니다
  • 두 번째 레벨 색인은 변수 (예 : 'A', 'B', 'C')의 레벨입니다.
  • 하나의 열에 'n' 레벨이 표시되는 시간
  • 두 번째 열에는이 비율로 표시되는 비율 인 '비율'이 포함됩니다. 예를 들어

:

enter image description here

는 사람이 MultiIndex DataFrame를 만들기위한 방법을 제안 할 수?

답변

3

당신이 meltgroupby를 사용하여이 작업을 수행 할 수있는 또 다른 방법 :

df_out = df.melt().groupby(['variable','value']).size().to_frame(name='n') 
df_out['proportion'] = df_out['n'].div(df_out.n.sum(level=0),level=0) 
print(df_out) 

출력 :

   n proportion 
variable value    
grade A  2   0.4 
     B  2   0.4 
     C  1   0.2 
year  2012 2   0.4 
     2013 3   0.6 

그리고, 당신이 정말로 미친 싶어하고 한 줄에 그것을 할 경우 :

(df.melt().groupby(['variable','value']).size().to_frame(name='n') 
    .pipe(lambda x: x.assign(proportion = x[['n']]/x.groupby(level=0).transform('sum')))) 

@Wen PCT 계산을 사용한 업그레이드 된 솔루션 :

단계 방법에 의해 516,
(df.melt().groupby(['variable','value']).size().to_frame(name='n') 
    .pipe(lambda x: x.assign(proportion = x['n'].div(x.n.sum(level=0),level=0)))) 
+0

관이 뛰어난 솔루션을 – Wen

+0

감사 스콧과 @Wen :-) 여기에 좋다. 내가 방법을 조금 더 쉽게 따라하기 때문에 나는 Wen의 대답을 받아 들였다. – tomp

+1

@tomp 모든 것이 좋다. 우리는 다른 사람들을 돕고 스스로를 배우는 것을 좋아합니다. 해피 코딩! –

0

각 변수를 루프에 쌓아서 DataFrame을 만들 수 있지만 비효율적 인 것처럼 보입니다. 예 :

d_end = [] 
for c in df.columns: 
    temp_df = pd.DataFrame(df[c].value_counts().rename('n')) 
    temp_df['proportion'] = temp_df['n']/temp_df['n'].sum() 
    temp_df['variable'] = c 
    temp_df.set_index(['variable',temp_df.index],inplace=True) 
    d_end.append(temp_df) 

df_end = pd.concat(d_end,axis=0) 

누군가가 더 좋은 방법을 제안하여 루프를 피할 수 있기를 바랍니다.

1

Stey : concat 사용시

df1 = df.groupby("grade").count() 
df2 = df.groupby("year").count() 

df1.columns = ['n'] 
df2.columns = ['n'] 
df1['proportion'] = df1.divide(df1.sum()) 
df2['proportion'] = df2.divide(df2.sum()) 

df_new = pd.concat([df1, df2], keys=['grade', 'year'], names=['variable']) 
  • 하나는 최 층 인덱스 될 keys를 할당 할 수있다. 또한 names=으로이 새 색인에 이름을 지정하십시오.

enter image description here

3

이 시도 할 수 있습니다 ..

df1=df.apply(pd.value_counts).stack().swaplevel(0,1).to_frame('n') 
df1['pct']=df1['n'].div(df1.n.sum(level=0),level=0) 
df1 
Out[89]: 
       n pct 
year 2012 2.0 0.4 
     2013 3.0 0.6 
grade A  2.0 0.4 
     B  2.0 0.4 
     C  1.0 0.2 
+0

내 솔루션에 백분율 계산을 추가해도 걱정하지 않으십니까? 나는 sumby level이 작동 할 때 groupby transform을 사용하는 것을 좋아하지 않는다. –

+2

@ScottBoston 진행 : -) 그건 내 것이 아니야, 우리의 :-) – Wen

+0

완벽 하군, 고마워! – tomp

관련 문제