2
votes

Comment extraire des nombres après un modèle de chaîne dans les pandas

J'ai le dataframe suivant dans les pandas

 m = re.search('TANK (\d+)', 'TANK 5', re.IGNORECASE)
 m.group(1)

Je veux extraire des nombres de la colonne text qui suit le modèle suivant

numéro après MS, HS et XP, numéro après TANK et numéro après Tank_

Dataframe souhaité

ID     text       new_text
1      T7MS1      1
2      T5HS2      2 
3      T3XP1      1
4      Tank_3     3
5      TANK 5     5
6      System     System

Je peux le faire en suivant pour 1 modèle

ID     text
1      T7MS1
2      T5HS2
3      T3XP1
4      Tank_3
5      TANK 5
6      System

Mais comment combiner tous les motifs en un et l'appliquer à la colonne.


3 commentaires

le nombre est-il toujours le dernier caractère?


Il semble que les réponses ci-dessous fonctionnent pour vous. Veuillez envisager d'accepter le meilleur. Si vous avez besoin d'aide supplémentaire, faites-le savoir.


Réponse mise à jour.


5 Réponses :


2
votes

Une fonction simple avec l'instruction if peut résoudre votre problème:

0         1
1         3
2         5
3    System
dtype: object

Ou vous pouvez utiliser ce modèle r "\ d + $" code > si vous ne voulez pas faire correspondre le numéro après un mot spécifique.
$ dans le modèle signifie la fin de la chaîne .

Il renvoie:

s = pd.Series(["T7MS1","Tank_3","TANK 5", "System"])

pattern= "[MS|HS|XP|TANK |Tank_](\d+)"
def fetch_num(txt):
    result = re.findall(pattern,txt)
    if result: # if matched
        return result[0]
    else:
        return txt

s.apply(fetch_num)

p >


1 commentaires

Votre expression régulière ne signifie pas ce que vous pensez que cela signifie. Il correspond uniquement au dernier caractère précédant le nombre.



1
votes

Si le nombre est toujours le dernier caractère du terme, vous pouvez simplement utiliser les méthodes de chaîne de la série Pandas, comme ceci:

df['new_text'] = df.text.str.slice(-1)

Sinon, car il y a des nombres au milieu que vous ne ne veux pas, une solution RegEx pourrait être possible, étant donné plus d'informations sur vos paramètres.


0 commentaires

3
votes

Si les nombres sont toujours la dernière lettre, il vous suffit d'utiliser Series.str [-1] :

df['new_text'] = df['new_text'].fillna(df['text'])
    id  text    new_text
0   1   T7MS1   1
1   2   T5HS2   2
2   3   T3XP1   1
3   4   Tank_3  3
4   5   TANK 5  5
5   6   System  System

Ou si vous voulez un numéro après MS, HS et XP, TANK et Tank_ uniquement: p>

df['new_text'] = df.text.str.extract(r'(?:MS|HS|XP|TANK |Tank_)(\d+)')
df

id  text    new_text
0   1   T7MS1    1
1   2   T5HS2    2
2   3   T3XP1    1
3   4   Tank_3   3
4   5   TANK 5   5

Vous pouvez remplir les valeurs nulles en utilisant:

df= pd.DataFrame({'id': [1, 2, 3, 4, 5],
                 'text': ['T7MS1', 'T5HS2', 'T3XP1', 'Tank_3', 'TANK 5']})
df

    id  text
0   1   T7MS1
1   2   T5HS2
2   3   T3XP1
3   4   Tank_3
4   5   TANK 5


df['new_text'] = df.text.str[-1]
df

   id   text    new_text
0   1   T7MS1    1
1   2   T5HS2    2
2   3   T3XP1    1
3   4   Tank_3   3
4   5   TANK 5   5


2 commentaires

Encore une chose, j'ai mis à jour la question, par exemple tout modèle en dehors de ce qui est mentionné dans la question doit rester le même dans la colonne new_text .


@Neil J'ai mis à jour ma réponse. Veuillez vérifier si cela vous aide.



1
votes

Je souhaite extraire des nombres de la colonne de texte qui suit motif

numéro après MS, HS et XP, numéro après TANK et numéro après Tank_

    ID    text new_text
0   1   T7MS1        1
1   2   T5HS2        2
2   3   T3XP1        1
3   4  Tank_3        3
4   5  TANK 5        5
5   6  System   System

Output

t['text'].apply(lambda x: re.findall(r'(?:MS|HS|XP|TANK |Tank_)(\d+)', x)[0] if re.findall(r'(?:MS|HS|XP|TANK |Tank_)(\d+)', x) else x)

Updated

Utilisation de alexis regex

   ID    text new_text
0   1   T7MS1        1
1   2   T5HS2        2
2   3   T3XP1        1
3   4  Tank_3        3
4   5  TANK 5        5

Sortie

l = ['MS','HS','XP','TANK','Tank_']
t['new_text'] = t['text'].apply(lambda x: re.findall(r'(?<=[{}\s])\d'.format( [d for d in l if d in x][0]),x)[0])

0 commentaires

4
votes

Utilisez l'expression régulière suivante pour combiner tous les préfixes:

(?:MS|HS|XP|TANK |Tank_)(\d+)

Puisque j'ai utilisé un "groupe non capturant" (?:) pour les préfixes, votre le numéro cible est toujours dans le groupe 1, comme dans votre code.


0 commentaires