2 votes

Comment incrémenter automatiquement un compteur par des valeurs répétées dans une colonne

J'ai un data frame avec la colonne name et j'ai besoin de créer la colonne seq, qui me permet d'identifier les différentes fois où un nom apparaît dans le data frame, il est important de préserver l'ordre.

import pandas as pd  

data = {'name': ['Tom', 'Joseph','Joseph','Joseph', 'Tom', 'Tom', 'John','Tom','Tom','John','Joseph']
        , 'seq': ['Tom 0', 'Joseph 0','Joseph 0','Joseph 0', 'Tom 1', 'Tom 1', 'John 0','Tom 2','Tom 2','John 1','Joseph 1']}  

df = pd.DataFrame(data)  

print(df) 

      name       seq
0      Tom     Tom 0
1   Joseph  Joseph 0
2   Joseph  Joseph 0
3   Joseph  Joseph 0
4      Tom     Tom 1
5      Tom     Tom 1
6     John    John 0
7      Tom     Tom 2
8      Tom     Tom 2
9     John    John 1
10  Joseph  Joseph 1

2voto

Corralien Points 6849

Créez un masque booléen pour savoir si le nom a changé par rapport à la ligne précédente. Ensuite, filtrez les deuxième, troisième, ... noms d'une séquence avant de regrouper par nom. cumcount incrémente le numéro de séquence et concatène enfin le nom et le numéro de séquence.

# Masque booléen
m = df['name'].ne(df['name'].shift())

# Créer le numéro de séquence
seq = df.loc[m].groupby('name').cumcount().astype(str) \
        .reindex(df.index, fill_value=pd.NA).ffill()

# Concaténer le nom et le seq
df['seq'] = df['name'] + ' ' + seq

Sortie :

>>> df
      name       seq
0      Tom     Tom 0
1   Joseph  Joseph 0
2   Joseph  Joseph 0
3   Joseph  Joseph 0
4      Tom     Tom 1
5      Tom     Tom 1
6     John    John 0
7      Tom     Tom 2
8      Tom     Tom 2
9     John    John 1
10  Joseph  Joseph 1

>>> m
0      True
1      True
2     False
3     False
4      True
5     False
6      True
7      True
8     False
9      True
10     True
Name: name, dtype: bool

1voto

ansev Points 26199

Vous devez vérifier l'existence d'un nouveau nom, puis créer un nouvel index pour chaque nom en utilisant groupby et cumsum, la série de chaînes résultante peut être concaténée avec str.cat

df['seq'] = df['name'].str.cat(
    df['name'].ne(df['name'].shift()).groupby(df['name']).cumsum().sub(1).astype(str),
    sep=' '
)

0voto

Zoff Dino Points 5010

En supposant que votre data frame soit indexé séquentiellement (0, 1, 2, 3, ...):

  1. Groupez le data frame par name
  2. Pour chaque groupe, appliquez un algorithme de lacunes et d'îlots : chaque fois que l'index saute de plus de 1, créez un nouvel îlot

    def sequencer(group): idx = group.index.to_series()

    Chaque fois que l'index a une lacune >1, crée un nouvel îlot

    return idx.diff().ne(1).cumsum().sub(1)

    seq = df.groupby('name').apply(sequencer).droplevel(0).rename('seq') df.merge(seq, left_index=True, right_index=True)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X