web-dev-qa-db-fra.com

TypeError: chaîne attendue ou objet de type octet - avec Python / NLTK Word_tokenize

J'ai un ensemble de données avec environ 40 colonnes et j'utilise .apply(Word_tokenize) sur 5 d'entre elles comme ceci: df['token_column'] = df.column.apply(Word_tokenize).

J'obtiens une TypeError pour une seule des colonnes, nous appellerons cette problem_column

TypeError: expected string or bytes-like object

Voici l'erreur complète (noms de colonne et df supprimés, et pii), je suis nouveau à Python et j'essaie toujours de comprendre quelles parties des messages d'erreur sont pertinentes:

TypeError                                 Traceback (most recent call last)
<ipython-input-51-22429aec3622> in <module>()
----> 1 df['token_column'] = df.problem_column.apply(Word_tokenize)

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\pandas\core\series.py in apply(self, func, convert_dtype, args, **kwds)
   2353             else:
   2354                 values = self.asobject
-> 2355                 mapped = lib.map_infer(values, f, convert=convert_dtype)
   2356 
   2357         if len(mapped) and isinstance(mapped[0], Series):

pandas\_libs\src\inference.pyx in pandas._libs.lib.map_infer (pandas\_libs\lib.c:66440)()

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\__init__.py in Word_tokenize(text, language, preserve_line)
    128     :type preserver_line: bool
    129     """
--> 130     sentences = [text] if preserve_line else sent_tokenize(text, language)
    131     return [token for sent in sentences
    132             for token in _treebank_Word_tokenizer.tokenize(sent)]

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\__init__.py in sent_tokenize(text, language)
     95     """
     96     tokenizer = load('tokenizers/punkt/{0}.pickle'.format(language))
---> 97     return tokenizer.tokenize(text)
     98 
     99 # Standard Word tokenizer.

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in tokenize(self, text, realign_boundaries)
   1233         Given a text, returns a list of the sentences in that text.
   1234         """
-> 1235         return list(self.sentences_from_text(text, realign_boundaries))
   1236 
   1237     def debug_decisions(self, text):

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in sentences_from_text(self, text, realign_boundaries)
   1281         follows the period.
   1282         """
-> 1283         return [text[s:e] for s, e in self.span_tokenize(text, realign_boundaries)]
   1284 
   1285     def _slices_from_text(self, text):

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in span_tokenize(self, text, realign_boundaries)
   1272         if realign_boundaries:
   1273             slices = self._realign_boundaries(text, slices)
-> 1274         return [(sl.start, sl.stop) for sl in slices]
   1275 
   1276     def sentences_from_text(self, text, realign_boundaries=True):

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in <listcomp>(.0)
   1272         if realign_boundaries:
   1273             slices = self._realign_boundaries(text, slices)
-> 1274         return [(sl.start, sl.stop) for sl in slices]
   1275 
   1276     def sentences_from_text(self, text, realign_boundaries=True):

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in _realign_boundaries(self, text, slices)
   1312         """
   1313         realign = 0
-> 1314         for sl1, sl2 in _pair_iter(slices):
   1315             sl1 = slice(sl1.start + realign, sl1.stop)
   1316             if not sl2:

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in _pair_iter(it)
    310     """
    311     it = iter(it)
--> 312     prev = next(it)
    313     for el in it:
    314         yield (prev, el)

C:\Users\egagne\AppData\Local\Continuum\Anaconda3\lib\site-packages\nltk\tokenize\punkt.py in _slices_from_text(self, text)
   1285     def _slices_from_text(self, text):
   1286         last_break = 0
-> 1287         for match in self._lang_vars.period_context_re().finditer(text):
   1288             context = match.group() + match.group('after_tok')
   1289             if self.text_contains_sentbreak(context):

TypeError: expected string or bytes-like object

Les 5 colonnes sont toutes des caractères/chaînes (comme vérifié dans SQL Server, SAS et en utilisant .select_dtypes(include=[object])).

Pour faire bonne mesure, j'ai utilisé .to_string() pour m'assurer que problem_column n'est vraiment rien d'autre qu'une chaîne, mais je continue à obtenir l'erreur. Si je traite les colonnes séparément, good_column1-good_column4 continue de fonctionner et problem_column générera toujours l'erreur.

J'ai cherché sur Google et à part supprimer tous les numéros de l'ensemble (ce que je ne peux pas faire, car ceux-ci sont significatifs), je n'ai trouvé aucun correctif supplémentaire.

7
LMGagne

C'est ce qui m'a donné le résultat souhaité.

def custom_tokenize(text):
    if not text:
        print('The text to be tokenized is a None type. Defaulting to blank string.')
        text = ''
    return Word_tokenize(text)
df['tokenized_column'] = df.column.apply(custom_tokenize)
1
LMGagne

Le problème est que vous avez des types Aucun (NA) dans votre DF. Essaye ça:

df['label'].dropna(inplace=True)
tokens = df['label'].apply(Word_tokenize)
15
Ekho

Essayer

from nltk.tokenize import Word_tokenize as WordTokenizer

def Word_tokenizer(data, col):
    token=[]
    for item in data[col]:
         token.append(WordTokenizer(item))

    return token

token = Word_tokenizer(df, column)
df. insert(index, 'token_column', token)
1
KerryChu

Il peut afficher une erreur car Word_tokenize() n'accepte qu'une seule chaîne à la fois. Vous pouvez parcourir les chaînes, puis les symboliser.

Par exemple:

text = "This is the first sentence. This is the second one. And this is the last one."
sentences = sent_tokenize(text)
words = [Word_tokenize(sent) for sent in sentences]
print(words)
1
Danish Shaikh

Il semble que certaines de vos colonnes ne soient pas de type chaîne/chaîne (numérique, peut-être?)

Vous pouvez récupérer une liste de colonnes qui sont string en utilisant df.blocks:

cols = df.blocks['object'].columns

Maintenant, utilisez df.applymap

df[cols] = df[cols].applymap(Word_tokenize)
0
coldspeed