En utilisant numpy.genfromtxt pour lire un fichier csv avec des chaînes contenant des virgules

J'essaie de lire dans un fichier csv avec numpy.genfromtxt mais certains des champs sont des chaînes qui contiennent des virgules. Les chaînes sont entre guillemets, mais numpy ne reconnaît pas les guillemets comme définissant une seule chaîne. Par exemple, avec les données dans 'T. csv':

2012, "Louisville KY", 3.5
2011, "Lexington, KY", 4.0

Le code

np.genfromtxt('t.csv', delimiter=',')

Produit l'erreur:

ValueError: certaines erreurs ont été détectées ! Ligne # 2 (obtenu 4 colonnes au lieu de 3)

La structure de données que je recherche est:

array([['2012', 'Louisville KY', '3.5'],
       ['2011', 'Lexington, KY', '4.0']], 
      dtype='|S13')

En regardant la documentation, Je ne vois aucune option pour y faire face. Y a-t-il un moyen de le faire avec numpy, ou Ai-je juste besoin de lire les données avec le module csv, puis de le convertir en un tableau numpy?

25
demandé sur joris 2013-07-30 00:11:02

4 réponses

Vous pouvez utiliser pandas (la bibliothèque par défaut pour travailler avec dataframes (données hétérogènes) dans scientific Python) pour cela. C'est read_csv je peux gérer ça. De la docs:

Quotechar: chaîne

The character to used to denote the start and end of a quoted item. Quoted items 
can include the delimiter and it will be ignored.

, La valeur par défaut est ". Un exemple:

In [1]: import pandas as pd

In [2]: from StringIO import StringIO

In [3]: s="""year, city, value
   ...: 2012, "Louisville KY", 3.5
   ...: 2011, "Lexington, KY", 4.0"""

In [4]: pd.read_csv(StringIO(s), quotechar='"', skipinitialspace=True)
Out[4]:
   year           city  value
0  2012  Louisville KY    3.5
1  2011  Lexington, KY    4.0

L'astuce ici est que vous devez également utiliser skipinitialspace=True pour traiter les espaces après le délimiteur de virgules.

En dehors d'un puissant lecteur csv, je peux aussi fortement conseiller pour utiliser des pandas avec les données hétérogènes que vous avez (l'exemple de sortie dans numpy que vous donnez sont toutes des chaînes, bien que vous puissiez utiliser des tableaux structurés).

19
répondu joris 2013-07-30 08:37:54

Le problème avec la virgule supplémentaire, np.genfromtxt ne traite pas de cela.

Une solution simple consiste à lire le fichier avec csv.reader() du module csv de python dans une liste, puis à le vider dans un tableau numpy si vous le souhaitez.

Si vous voulez vraiment utiliser np.genfromtxt, note qu'il peut prendre des itérateurs au lieu de fichiers, par exemple np.genfromtxt(my_iterator, ...). Ainsi, vous pouvez envelopper un csv.reader dans un itérateur et le donner à np.genfromtxt.

Cela irait quelque chose comme ceci:

import csv
import numpy as np

np.genfromtxt(("\t".join(i) for i in csv.reader(open('myfile.csv'))), delimiter="\t")

Cela remplace essentiellement à la volée seulement les virgules appropriées avec des onglets.

10
répondu Bitwise 2015-12-29 15:33:38

Si vous utilisez un numpy vous voulez probablement travailler avec numpy.ndarray. Cela vous donnera un numpy.ndarray:

import pandas
data = pandas.read_csv('file.csv').as_matrix()

Les Pandas géreront correctement le cas" Lexington, KY "

3
répondu Michael Yurin 2016-05-05 21:22:16

Faire une meilleure fonction qui associe la puissance de la norme csv module et Numpy est recfromcsv. Par exemple, le module csv a un bon contrôle et une bonne personnalisation des dialectes, des guillemets, des caractères d'échappement, etc., vous pouvez les ajouter à l'exemple ci-dessous.

L'exemple de fonction genfromcsv_mod ci-dessous se lit dans un fichier csv compliqué similaire à ce que Microsoft Excel voit, qui peut contenir des virgules dans les champs entre guillemets. En interne, la fonction a une fonction de générateur qui réécrit chaque ligne avec des délimiteurs de tabulation.

import csv
import numpy as np

def recfromcsv_mod(fname, **kwargs):
    def rewrite_csv_as_tab(fname):
        with open(fname, 'rb') as fp:
            reader = csv.reader(fp)
            for row in reader:
                yield '\t'.join(row)
    return np.recfromcsv(rewrite_csv_as_tab(fname), delimiter='\t', **kwargs)

# Use it to read a CSV file into a record array
x = recfromcsv_mod('t.csv', case_sensitive=True)
1
répondu Mike T 2017-01-30 20:45:15