combinaisons uniques de valeurs dans les colonnes sélectionnées dans la trame de données pandas et le nombre

99

J'ai mes données dans la trame de données pandas comme suit:

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

Donc, mes données ressemblent à ceci

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

Je voudrais le transformer en un autre bloc de données. La sortie attendue peut être affichée dans le script python suivant:

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

Donc, ma sortie attendue ressemble à ceci

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

En fait, je peux réussir à trouver toutes les combinaisons et à les compter en utilisant la commande suivante: mytable = df1.groupby(['A','B']).size()

Cependant, il s'avère que ces combinaisons se trouvent dans une seule colonne. Je voudrais séparer chaque valeur d'une combinaison dans une colonne différente et ajouter également une colonne supplémentaire pour le résultat du comptage. Est-il possible de faire ça? Puis-je avoir vos suggestions? Merci d'avance.

Ratchainant Thammasudjarit
la source

Réponses:

166

Vous pouvez groupbysur les cols 'A' et 'B' et appeler sizeet puis reset_indexet renamela colonne générée:

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

mettre à jour

Une petite explication, en regroupant sur les 2 colonnes, cela regroupe les lignes où les valeurs A et B sont les mêmes, on appelle sizece qui renvoie le nombre de groupes uniques:

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

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

Alors maintenant, pour restaurer les colonnes groupées, nous appelons 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

Cela restaure les indices mais l'agrégation de taille est transformée en une colonne générée 0, nous devons donc renommer ceci:

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

groupbyaccepte l'argument as_indexque nous aurions pu définir pour Falsene pas faire des colonnes groupées l'index, mais cela génère un serieset vous devrez toujours restaurer les index et ainsi de suite ....:

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
la source
1

Légèrement apparenté, je cherchais les combinaisons uniques et j'ai proposé cette méthode:

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

Et si vous voulez seulement affirmer que toutes les combinaisons sont uniques:

df1.set_index(['A','B']).index.is_unique
Martin Alexandersson
la source
Je ne savais pas set_index(). Continué à essayer d'utiliser groupby()pour regrouper des lignes avec une paire de colonnes commune particulière. Incroyable, merci!
user3290553
0

Mettre la très belle réponse de @ EdChum dans une fonction count_unique_index. La méthode unique ne fonctionne que sur les séries pandas, pas sur les trames de données. La fonction ci-dessous reproduit le comportement de la fonction unique dans R:

unique renvoie un vecteur, un bloc de données ou un tableau comme x mais avec les éléments / lignes en double supprimés.

Et ajoute un décompte des occurrences comme demandé par l'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
la source
0

Je n'ai pas fait de test de temps avec ça mais c'était amusant d'essayer. En gros, convertissez deux colonnes en une colonne de tuples. Maintenant, convertissez cela en dataframe, faites 'value_counts ()' qui trouve les éléments uniques et les compte. Jouez à nouveau avec zip et mettez les colonnes dans l'ordre que vous voulez. Vous pouvez probablement rendre les étapes plus élégantes mais travailler avec des tuples me semble plus naturel pour ce problème

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