combinazioni uniche di valori nelle colonne selezionate nel frame di dati e conteggio dei panda


99

Ho i miei dati nel frame di dati panda come segue:

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

Quindi, i miei dati sono così

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

Vorrei trasformarlo in un altro frame di dati. L'output previsto può essere mostrato nel seguente script python:

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

Quindi, il mio output previsto è simile a questo

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

In realtà, posso trovare tutte le combinazioni e contarle usando il seguente comando: mytable = df1.groupby(['A','B']).size()

Tuttavia, risulta che tali combinazioni sono in una singola colonna. Vorrei separare ogni valore in una combinazione in una colonna diversa e aggiungere anche un'altra colonna per il risultato del conteggio. è possibile farlo? Posso avere i tuoi suggerimenti? Grazie in anticipo.

Risposte:


166

Puoi groupbysulle colonne 'A' e 'B' e chiamare sizee poi reset_indexe renamela colonna generata:

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

aggiornare

Una piccola spiegazione, raggruppando sulle 2 colonne, questo raggruppa le righe in cui i valori A e B sono uguali, chiamiamo sizeche restituisce il numero di gruppi univoci:

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

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

Quindi ora per ripristinare le colonne raggruppate, chiamiamo 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

Questo ripristina gli indici ma l'aggregazione delle dimensioni viene trasformata in una colonna generata 0, quindi dobbiamo rinominarla:

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

groupbyaccetta l'arg as_indexche avremmo potuto impostare in Falsemodo da non rendere le colonne raggruppate l'indice, ma questo genera un seriese dovresti comunque ripristinare gli indici e così via ....:

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

Leggermente imparentato, stavo cercando le combinazioni uniche e ho ideato questo metodo:

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

E se vuoi solo affermare che tutte le combinazioni sono uniche:

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

Non sapevo set_index(). Ho continuato a provare a utilizzare groupby()per raggruppare insieme righe con una particolare coppia di colonne comune. Fantastico, grazie!
user3290553

0

Posizionare la risposta molto carina di @ EdChum in una funzione count_unique_index. Il metodo unico funziona solo sulle serie di panda, non sui frame di dati. La funzione seguente riproduce il comportamento della funzione unica in R:

unique restituisce un vettore, un data frame o un array come x ma con elementi / righe duplicati rimossi.

E aggiunge un conteggio delle occorrenze come richiesto dall'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

Non ho fatto il test del tempo con questo ma è stato divertente provare. Fondamentalmente converti due colonne in una colonna di tuple. Ora la conversione che a un dataframe, fare 'value_counts ()' che trova gli elementi unici e li conta. Giocherella di nuovo con zip e metti le colonne nell'ordine che desideri. Probabilmente puoi rendere i passaggi più eleganti, ma lavorare con le tuple mi sembra più naturale per questo problema

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']]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.