web-dev-qa-db-fra.com

pandas to_csv: ascii ne peut pas coder le caractère

J'essaie de lire et d'écrire une trame de données dans un fichier délimité par des tuyaux. Certains caractères sont des lettres non romaines (`, ç, ñ, etc.). Mais ça casse quand j'essaie d'écrire les accents en ASCII.

df = pd.read_csv('filename.txt',sep='|', encoding='utf-8')
<do stuff>
newdf.to_csv('output.txt', sep='|', index=False, encoding='ascii')

-------

  File "<ipython-input-63-ae528ab37b8f>", line 21, in <module>
    newdf.to_csv(filename,sep='|',index=False, encoding='ascii')

  File "C:\Users\aliceell\AppData\Local\Continuum\Anaconda3\lib\site-packages\pandas\core\frame.py", line 1344, in to_csv
    formatter.save()

  File "C:\Users\aliceell\AppData\Local\Continuum\Anaconda3\lib\site-packages\pandas\formats\format.py", line 1551, in save
    self._save()

  File "C:\Users\aliceell\AppData\Local\Continuum\Anaconda3\lib\site-packages\pandas\formats\format.py", line 1652, in _save
    self._save_chunk(start_i, end_i)

  File "C:\Users\aliceell\AppData\Local\Continuum\Anaconda3\lib\site-packages\pandas\formats\format.py", line 1678, in _save_chunk
    lib.write_csv_rows(self.data, ix, self.nlevels, self.cols, self.writer)

  File "pandas\lib.pyx", line 1075, in pandas.lib.write_csv_rows (pandas\lib.c:19767)

UnicodeEncodeError: 'ascii' codec can't encode character '\xb4' in position 7: ordinal not in range(128)

Si je change to_csv pour avoir un encodage utf-8, alors je ne peux pas lire le fichier correctement:

newdf.to_csv('output.txt',sep='|',index=False,encoding='utf-8')
pd.read_csv('output.txt', sep='|')

> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb4 in position 2: invalid start byte

Mon objectif est d'avoir un fichier délimité par des tuyaux qui conserve les accents et les caractères spéciaux.

De plus, existe-t-il un moyen simple de déterminer sur quelle ligne read_csv se casse? Pour le moment, je ne sais pas comment l'obtenir pour me montrer le (s) mauvais caractère (s).

8
ale19

Vous avez des caractères qui ne sont pas ASCII et ne peuvent donc pas être encodés comme vous essayez de le faire. J'utiliserais simplement utf-8 comme suggéré dans un commentaire.

Pour vérifier quelles lignes sont à l'origine du problème, vous pouvez essayer quelque chose comme ceci:

def is_not_ascii(string):
    return string is not None and any([ord(s) >= 128 for s in string])

df[df[col].apply(is_not_ascii)]

Vous devrez spécifier la colonne col que vous testez.

7
AlexG

Vérifiez la réponse ici

C'est une solution beaucoup plus simple:

newdf.to_csv("C:/tweetDF", sep='\t', encoding = 'utf-8')
35
Ohad Zadok

Une autre solution consiste à utiliser les fonctions de chaîne encoder/décoder avec l'option 'ignorer', mais cela supprimera les caractères non ascii:

df['text'] = df['text'].apply(lambda x: x.encode('ascii', 'ignore').decode('ascii'))

0
Edward Weinert