パンダのデータフレームとカウントで選択した列の値の一意の組み合わせ


99

私はパンダのデータフレームに次のようにデータを持っています:

df1 = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],
                   'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})

だから、私のデータはこのようになります

----------------------------
index         A        B
0           yes      yes
1           yes       no
2           yes       no
3           yes       no
4            no      yes
5            no      yes
6           yes       no
7           yes      yes
8           yes      yes
9            no       no
-----------------------------

別のデータフレームに変換したいと思います。予想される出力は、次のPythonスクリプトで表示できます。

output = pd.DataFrame({'A':['no','no','yes','yes'],'B':['no','yes','no','yes'],'count':[1,2,4,3]})

だから、私の期待される出力は次のようになります

--------------------------------------------
index      A       B       count
--------------------------------------------
0         no       no        1
1         no      yes        2
2        yes       no        4
3        yes      yes        3
--------------------------------------------

実際には、次のコマンドを使用して、すべての組み合わせを見つけてそれらを数えることができます。 mytable = df1.groupby(['A','B']).size()

ただし、そのような組み合わせは1つの列にあることがわかります。組み合わせの各値を別の列に分けて、カウント結果の列を1つ追加します。それは可能ですか?提案をいただけますか?前もって感謝します。

回答:


166

groupbycols 'A'と 'B'を呼び出してsizeから、reset_indexそしてrename生成された列を呼び出すことができます。

In [26]:

df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
Out[26]:
     A    B  count
0   no   no      1
1   no  yes      2
2  yes   no      4
3  yes  yes      3

更新

簡単な説明、2つの列でグループ化することにより、AとBの値が同じである行をグループ化します。これを呼び出すsizeと、一意のグループの数が返されます。

In[202]:
df1.groupby(['A','B']).size()

Out[202]: 
A    B  
no   no     1
     yes    2
yes  no     4
     yes    3
dtype: int64

そこで、グループ化された列を復元するために、次を呼び出しますreset_index

In[203]:
df1.groupby(['A','B']).size().reset_index()

Out[203]: 
     A    B  0
0   no   no  1
1   no  yes  2
2  yes   no  4
3  yes  yes  3

これによりインデックスが復元されますが、サイズの集計は生成された列に変換される0ため、名前を変更する必要があります。

In[204]:
df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})

Out[204]: 
     A    B  count
0   no   no      1
1   no  yes      2
2  yes   no      4
3  yes  yes      3

groupbyグループ化された列をインデックスにしないようにas_index設定できるarg を受け入れFalseますが、これによりが生成seriesされ、インデックスなどを復元する必要があります。

In[205]:
df1.groupby(['A','B'], as_index=False).size()

Out[205]: 
A    B  
no   no     1
     yes    2
yes  no     4
     yes    3
dtype: int64

1

少し関連して、私はユニークな組み合わせを探していました、そして私はこの方法を思いつきました:

def unique_columns(df,columns):

    result = pd.Series(index = df.index)

    groups = meta_data_csv.groupby(by = columns)
    for name,group in groups:
       is_unique = len(group) == 1
       result.loc[group.index] = is_unique

    assert not result.isnull().any()

    return result

そして、すべての組み合わせが一意であることを主張したい場合:

df1.set_index(['A','B']).index.is_unique

について知りませんでしたset_index()groupby()特定の一般的な列のペアで行をグループ化するために使用しようとし続けました。すばらしい、ありがとう!
user3290553

0

@EdChumの非常に良い答えを関数に配置するcount_unique_index。独自の方法は、パンダシリーズでのみ機能し、データフレームでは機能しません。以下の関数は、Rの一意の関数の動作を再現します。

uniqueは、xのようなベクトル、データフレーム、または配列を返しますが、重複する要素/行は削除されています。

また、OPの要求に応じて発生回数を追加します。

df1 = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],                                                                                             
                    'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})                                                                                               
def count_unique_index(df, by):                                                                                                                                                 
    return df.groupby(by).size().reset_index().rename(columns={0:'count'})                                                                                                      

count_unique_index(df1, ['A','B'])                                                                                                                                              
     A    B  count                                                                                                                                                                  
0   no   no      1                                                                                                                                                                  
1   no  yes      2                                                                                                                                                                  
2  yes   no      4                                                                                                                                                                  
3  yes  yes      3

0

私はこれで時間テストをしていませんが、試すのは楽しかったです。基本的に、2つの列をタプルの1つの列に変換します。それをデータフレームに変換、一意の要素を見つけてそれらカウントする「value_counts()」を実行します。もう一度zipをいじって、列を必要な順序に配置します。あなたはおそらくステップをよりエレガントにすることができますが、タプルでの作業はこの問題では私にとってより自然に思えます

b = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})

b['count'] = pd.Series(zip(*[b.A,b.B]))
df = pd.DataFrame(b['count'].value_counts().reset_index())
df['A'], df['B'] = zip(*df['index'])
df = df.drop(columns='index')[['A','B','count']]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.