kombinasi unik dari nilai di kolom yang dipilih dalam bingkai dan hitungan data panda

109

Saya memiliki data saya dalam bingkai data panda sebagai berikut:

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']})

Jadi, data saya terlihat seperti ini

----------------------------
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
-----------------------------

Saya ingin mengubahnya menjadi bingkai data lain. Output yang diharapkan dapat ditampilkan dalam skrip python berikut:

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

Jadi, keluaran yang saya harapkan terlihat seperti ini

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

Sebenarnya, saya dapat mencapai untuk menemukan semua kombinasi dan menghitungnya dengan menggunakan perintah berikut: mytable = df1.groupby(['A','B']).size()

Namun, ternyata kombinasi tersebut ada dalam satu kolom. Saya ingin memisahkan setiap nilai dalam kombinasi ke kolom yang berbeda dan juga menambahkan satu kolom lagi untuk hasil penghitungan. Apakah mungkin melakukan itu? Bolehkah saya mendapatkan saran anda Terima kasih sebelumnya.

Ratchainant Thammasudjarit
sumber

Jawaban:

176

Anda dapat groupbydi kolom 'A' dan 'B' dan memanggil sizedan kemudian reset_indexdan renamekolom yang dihasilkan:

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

memperbarui

Sedikit penjelasan, dengan mengelompokkan pada 2 kolom, ini mengelompokkan baris di mana nilai A dan B sama, kita sebut sizeyang mengembalikan jumlah grup unik:

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

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

Jadi sekarang untuk memulihkan kolom yang dikelompokkan, kami memanggil 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

Ini mengembalikan indeks tetapi agregasi ukuran diubah menjadi kolom yang dihasilkan 0, jadi kita harus mengganti namanya:

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

groupbytidak menerima arg as_indexyang bisa kita atur Falsesehingga tidak membuat kolom yang dikelompokkan menjadi indeks, tetapi ini menghasilkan a seriesdan Anda masih harus memulihkan indeks dan seterusnya ....:

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
EdChum
sumber
2

Sedikit terkait, saya mencari kombinasi unik dan saya menemukan metode ini:

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

Dan jika Anda hanya ingin menegaskan bahwa semua kombinasi itu unik:

df1.set_index(['A','B']).index.is_unique
Martin Alexandersson
sumber
Tidak tahu tentang set_index(). Terus mencoba menggunakan groupby()untuk mengelompokkan bersama baris dengan pasangan kolom umum tertentu. Luar biasa, terima kasih!
pengguna3290553
0

Menempatkan jawaban yang sangat bagus dari @ EdChum ke dalam sebuah fungsi count_unique_index. Metode unik hanya berfungsi pada seri pandas, bukan pada bingkai data. Fungsi di bawah ini mereproduksi perilaku fungsi unik di R:

unique mengembalikan vektor, bingkai data atau larik seperti x tetapi dengan elemen / baris duplikat dihapus.

Dan menambahkan hitungan kejadian seperti yang diminta oleh 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
Paul Rougieux
sumber
0

Saya belum melakukan uji waktu dengan ini tetapi menyenangkan untuk dicoba. Pada dasarnya mengubah dua kolom menjadi satu kolom tupel. Sekarang ubah itu menjadi dataframe, lakukan 'value_counts ()' yang menemukan elemen unik dan menghitungnya. Bermain-main dengan zip lagi dan letakkan kolom sesuai urutan yang Anda inginkan. Anda mungkin dapat membuat langkah-langkahnya lebih elegan tetapi bekerja dengan tupel tampaknya lebih alami bagi saya untuk masalah ini

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']]
MikeB2019x
sumber