2017-12-28 26 views
3

私はいくつかのカテゴリ変数を含むPandas DataFrameを持っています。たとえば:カウントダウンとパーセンテージを持つカテゴリ変数のPandas DataFrameを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

私は、次のプロパティを持つマルチインデックスのデータフレームにこれを変換したい:

  • 第1レベルインデックスは、変数名(例えば「グレード」)である
  • 2番目のレベルのインデックスは、変数内のレベルです(例: 'A'、 'B'、 'C​​')
  • 1つの列に 'n'レベルの数が表示されます
  • 2番目の列には「割合」が含まれ、この割合で表されます。たとえば、

enter image description here

誰もがこのマルチインデックスデータフレームを作成するための方法を提案してもらえますか?

答えて

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を使用したアップグレードソリューション:

0123ステップ法による
(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:

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']) 
  • concatを使用しながら、一方は最外層指標であろう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

あなたのパーセント計算を自分のソリューションに追加してもいいですか?私は合計レベルがあまりにも機能するときにgroupby変換を使うのは好きではありません。 –

+2

@ScottBoston行く: - )それは私のものではない、それは私たち:-) – Wen

+0

完璧、ありがとう! – tomp

関連する問題