2016-08-08 21 views
4

複数のクロス集計を1つにマージしようとしています。提供されるデータは明らかにテスト目的のためだけであることに注意してください。実際のデータははるかに大きいので、私にとっては効率が非常に重要です。Pythonでクロス集計をマージする

クロスタブが生成され、リストされ、word列のラムダ関数とマージされます。しかし、この合併の結果は私が期待するものではありません。私は問題は、merge関数が失敗する結果となるdropna = Falseを使用しても、クロスタブのNA値だけの列が削除されているということだと思います。最初にコードを表示し、その後に中間データとエラーを表示します。

import pandas as pd 
import numpy as np 
import functools as ft 

def main(): 
    # Create dataframe 
    df = pd.DataFrame(data=np.zeros((0, 3)), columns=['word','det','source']) 
    df["word"] = ('banana', 'banana', 'elephant', 'mouse', 'mouse', 'elephant', 'banana', 'mouse', 'mouse', 'elephant', 'ostrich', 'ostrich') 
    df["det"] = ('a', 'the', 'the', 'a', 'the', 'the', 'a', 'the', 'a', 'a', 'a', 'the') 
    df["source"] = ('BE', 'BE', 'BE', 'NL', 'NL', 'NL', 'FR', 'FR', 'FR', 'FR', 'FR', 'FR') 

    create_frequency_list(df) 

def create_frequency_list(df): 
    # Create a crosstab of ALL values 
    # NOTE that dropna = False does not seem to work as expected 
    total = pd.crosstab(df.word, df.det, dropna = False) 
    total.fillna(0) 
    total.reset_index(inplace=True) 
    total.columns = ['word', 'a', 'the'] 

    crosstabs = [total] 

    # For the column headers, multi-level 
    first_index = [('total','total')] 
    second_index = [('a','the')] 

    # Create crosstabs per source (one for BE, one for NL, one for FR) 
    # NOTE that dropna = False does not seem to work as expected 
    for source, tempDf in df.groupby('source'): 
     crosstab = pd.crosstab(tempDf.word, tempDf.det, dropna = False) 
     crosstab.fillna(0) 
     crosstab.reset_index(inplace=True) 
     crosstab.columns = ['word', 'a', 'the'] 
     crosstabs.append(crosstab) 

     first_index.extend((source,source)) 
     second_index.extend(('a','the')) 

    # Just for debugging: result as expected 
    for tab in crosstabs: 
     print(tab) 

    merged = ft.reduce(lambda left,right: pd.merge(left,right, on='word'), crosstabs).set_index('word') 

    # UNEXPECTED RESULT 
    print(merged)  

    arrays = [first_index, second_index] 

    # Throws error: NotImplementedError: > 1 ndim Categorical are not supported at this time 
    columns = pd.MultiIndex.from_arrays(arrays) 

    df_freq = pd.DataFrame(data=merged.as_matrix(), 
         columns=columns, 
         index = crosstabs[0]['word']) 
    print(df_freq) 

main() 

個々のクロス集計:期待できないとして。 NAの列はデータフレームがどの順番になりますおそらく台無しにマージをお互いの間ですべての値を共有しないことを意味することに

 word a the 
0 banana 2 1 
1 elephant 1 2 
2  mouse 2 2 
3 ostrich 1 1 

     word a the 
0 banana 1 1 
1 elephant 0 1 

     word a the 
0 banana 1 0 
1 elephant 1 0 
2  mouse 1 1 
3 ostrich 1 1 

     word a the 
0 elephant 0 1 
1  mouse 1 1 

を落としています。

マージ:私は、問題を早期に開始し伝えることができるように限り

# NotImplementedError: > 1 ndim Categorical are not supported at this time 
columns = pd.MultiIndex.from_arrays(arrays) 

:期待できないとして、明らかに

  a_x the_x a_y the_y a_x the_x a_y the_y 
word              
elephant 1  2 0  1 1  0 0  1 

しかし、エラーが列のみの割り当てで投げますNAsと一緒に、そしてすべてを失敗させる。しかし、私はPythonで十分な経験がないので、私は確かに知ることができません。私が期待したもの

は、マルチインデックス出力した:

source  total  BE   FR   NL 
    det   a the  a the  a the  a the 
    word 
0 banana  2 1  1 1  1 0  0 0 
1 elephant 1 2  0 1  1 0  0 1 
2 mouse  2 2  0 0  1 1  1 1 
3 ostrich  1 1  0 0  1 1  0 0 

答えて

2

私はちょうどあなたが何をしたいあなたを得るためのより良い方法を与えることにした:

は、私は私のpd.crosstabなどとしてプロキシにdf.groupby([col1, col2]).size().unstack()を使用します一般的なルール。 sourceのすべてのグループに対してクロスタブを実行しようとしていました。私はそれを既存のグループとうまく合わせることができます。df.groupby([col1, col2, col3]).size().unstack([2, 1])

sort_index(1).fillna(0).astype(int)はちょっとしたものです。

もっとよく理解したい場合は、次のことを試してみて、あなたが得るものを見て:

  • df.groupby(['word', 'gender']).size()
  • df.groupby(['word', 'gender', 'source']).size()

unstackstackではなく、またその逆の列にインデックスにあったものを取得するための便利な方法です。 unstack([2, 1])は、インデックスレベルがスタック解除される順序を指定しています。

最後に、私はxtabsstackをもう一度とり、unstackpd.concatに合わせて合計します。 Voilà!

xtabs = df.groupby(df.columns.tolist()).size() \ 
      .unstack([2, 1]).sort_index(1).fillna(0).astype(int) 

pd.concat([xtabs.stack().sum(1).rename('total').to_frame().unstack(), xtabs], axis=1) 

enter image description here

あなたのコードは次のようになります。

import pandas as pd 
import numpy as np 
import functools as ft 

def main(): 
    # Create dataframe 
    df = pd.DataFrame(data=np.zeros((0, 3)), columns=['word','gender','source']) 
    df["word"] = ('banana', 'banana', 'elephant', 'mouse', 'mouse', 'elephant', 'banana', 'mouse', 'mouse', 'elephant', 'ostrich', 'ostrich') 
    df["gender"] = ('a', 'the', 'the', 'a', 'the', 'the', 'a', 'the', 'a', 'a', 'a', 'the') 
    df["source"] = ('BE', 'BE', 'BE', 'NL', 'NL', 'NL', 'FR', 'FR', 'FR', 'FR', 'FR', 'FR') 

    return create_frequency_list(df) 

def create_frequency_list(df): 
    xtabs = df.groupby(df.columns.tolist()).size() \ 
       .unstack([2, 1]).sort_index(1).fillna(0).astype(int) 

    total = xtabs.stack().sum(1) 
    total.name = 'total' 
    total = total.to_frame().unstack() 

    return pd.concat([total, xtabs], axis=1) 

main() 
+0

は、これまでの努力をありがとうございました。どこに置くべきか説明できますか? 'create_frequency_list'の中のすべてを削除してコードで置き換えようとしましたが、' 'str 'オブジェクトは呼び出し可能ではありません.'というエラーがコードの最後の行に表示されます。その次に、コード内で何が起こっているのかをもっと徹底的に説明できますか?私が言ったように私は初心者ですが、私は本当に学びたいと思っています。 –

+0

@BramVanroy私の投稿を更新しました。 – piRSquared

+0

コードをコピーして貼り付けたのに、同じエラーが表示されます。ここに[ブレークダウン](http://pastebin.com/NQwLhp6R)があります。 Pythonの実行3.4.3。 –

関連する問題