4 votes

Pandas donne une erreur à partir de str.extractall('#')

J'essaie de filtrer toutes les # mots-clés du texte du tweet. J'utilise str.extractall() pour extraire tous les mots-clés avec # mots-clés. C'est la première fois que je travaille sur le filtrage des mots-clés à partir du tweetText en utilisant pandas. Les entrées, le code, le résultat attendu et l'erreur sont donnés ci-dessous.

Entrée :

userID,tweetText 
01, home #sweet home
01, #happy #life 
02, #world peace
03, #all are one
04, world tour

et ainsi de suite... le fichier de données total est de la taille d'un Go de tweets raclés avec plusieurs autres colonnes. Mais je ne suis intéressé que par deux colonnes.

Code :

import re
import pandas as pd

data = pd.read_csv('Text.csv', index_col=0, header=None, names=['userID', 'tweetText'])

fout = data['tweetText'].str.extractall('#')

print fout 

Résultats attendus :

userID,tweetText 
01,#sweet
01,#happy 
01,#life 
02,#world
03,#all

Erreur :

Traceback (most recent call last):
  File "keyword_split.py", line 7, in <module>
    fout = data['tweetText'].str.extractall('#')
  File "/usr/local/lib/python2.7/dist-packages/pandas/core/strings.py", line 1621, in extractall
    return str_extractall(self._orig, pat, flags=flags)
  File "/usr/local/lib/python2.7/dist-packages/pandas/core/strings.py", line 694, in str_extractall
    raise ValueError("pattern contains no capture groups")
ValueError: pattern contains no capture groups

Merci d'avance pour votre aide. Quel serait le moyen le plus simple de filtrer les mots-clés en fonction de l'identifiant de l'utilisateur ?

Mise à jour de la sortie :

Lorsqu'elle est utilisée seule, la sortie est comme ci-dessus s.name = "tweetText" data_1 = data[~data['tweetText'].isnull()]

Dans ce cas, la sortie est vide [] et l'ID de l'utilisateur est toujours listé et pour ceux qui ont des mots-clés, il s'agit d'un tableau de mots-clés et non d'une liste.

Lorsqu'il n'est utilisé que de cette manière, la sortie est celle dont nous avons besoin mais avec NAN

s.name = "tweetText"
data_2 = data_1.drop('tweetText', axis=1).join(s)

La sortie ici est le format correct, mais ceux qui n'ont pas de mots clés a encore considéré et a NAN

Si c'est possible, nous devons négliger ces identifiants et ne pas les faire apparaître dans la sortie. Dans les étapes suivantes, j'essaie de calculer la fréquence des mots-clés dans lesquels l'identifiant de l'utilisateur est utilisé. NAN ou vide [] seront également comptabilisés et cette fréquence peut compromettre la classification dans un avenir lointain.

enter image description here

4voto

Abdou Points 8101

Si vous n'êtes pas trop attaché à l'utilisation extractall vous pouvez essayer ce qui suit pour obtenir votre résultat final :

from io import StringIO
import pandas as pd
import re

data_text = """userID,tweetText
01, home #sweet home
01, #happy #life 
02, #world peace
03, #all are one
"""

data = pd.read_csv(StringIO(data_text),header=0)

data['tweetText'] = data.tweetText.apply(lambda x: re.findall('#(?=\w+)\w+',x))
s = data.apply(lambda x: pd.Series(x['tweetText']),axis=1).stack().reset_index(level=1, drop=True)
s.name = "tweetText"
data = data.drop('tweetText', axis=1).join(s)

     userID tweetText
0       1    #sweet
1       1    #happy
1       1     #life
2       2    #world
3       3      #all
4       4       NaN

Vous laissez tomber les lignes où la colonne textTweet retourne Nan en procédant comme suit :

data = data[~data['tweetText'].isnull()]

Cela devrait revenir :

   userID tweetText
0       1    #sweet
1       1    #happy
1       1     #life
2       2    #world
3       3      #all

J'espère que cela vous aidera.

3voto

Mettez des accolades dans vos calculs :

fout = data['tweetText'].str.extractall('(#)')

au lieu de

fout = data['tweetText'].str.extractall('#')

J'espère que cela fonctionnera

0voto

Merlin Points 8274

Essayez ça :

Comme il filtre pour '#', votre NAN ne devrait pas exister.

    data = pd.read_csv(StringIO(data_text),header=0, index_col=0 )
    data = data["tweetText"].str.split(' ', expand=True).stack().reset_index().rename(columns = {0:"tweetText"}).drop('level_1', 1)
    data = data[data['tweetText'].str[0] == "#"].reset_index(drop=True) 

     userID tweetText
0       1    #sweet
1       1    #happy
2       1     #life
3       2    #world
4       3      #all

Méthode @Abdou :

def try1():
     data = pd.read_csv(StringIO(data_text),header=0)
     data['tweetText'] = data.tweetText.apply(lambda x: re.findall('#(?=\w+)\w+',x))
     s = data.apply(lambda x: pd.Series(x['tweetText']),axis=1).stack().reset_index(level=1, drop=True)
     s.name = "tweetText"
     data = data.drop('tweetText', axis=1).join(s)
     data = data[~data['tweetText'].isnull()]

%timeit try1()
 100 loops, best of 3: 7.71 ms per loop

Méthode @Merlin

def try2():
    data = pd.read_csv(StringIO(data_text),header=0, index_col=0 )
    data = data["tweetText"].str.split(' ', expand=True).stack().reset_index().rename(columns = {'level_0':'userID',0:"tweetText"}).drop('level_1', 1)
    data = data[data['tweetText'].str[0] == "#"].reset_index(drop=True)

%timeit try2()
100 loops, best of 3: 5.36 ms per loop

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