2010-06-05 14 views
3

J'ai essayé de trouver un moyen efficace et flexible d'analyser les fichiers CSV en Python, mais aucune des options standard ne semble correspondre à la facture. Je suis tenté d'écrire le mien mais je pense qu'une combinaison de ce qui existe dans numpy/scipy et du module csv peut faire ce dont j'ai besoin, et donc je ne veux pas réinventer la roue. Je voudrais les caractéristiques standard de pouvoir spécifier des délimiteurs, spécifier si oui ou non il y a un en-tête, combien de lignes à sauter, délimiteur de commentaires, quelles colonnes ignorer, etc. La caractéristique centrale qui me manque est d'être capable d'analyser les fichiers CSV d'une manière qui gère avec élégance à la fois les données de chaîne et les données numériques. Beaucoup de mes fichiers CSV ont des colonnes qui contiennent des chaînes (pas nécessairement de même longueur) et des données numériques. Je voudrais pouvoir avoir une fonctionnalité de tableau numpy pour ces données numériques, mais aussi pouvoir accéder aux chaînes. Par exemple, supposons que mon fichier ressemble à ceci (colonnes imaginer sont séparés par des tabulations):Manière définitive d'analyser les fichiers CSV alphanumériques en Python avec scipy/numpy

# my file 
name favorite_integer favorite_float1 favorite_float2 short_description 
johnny 5 60.2 0.52 johnny likes fruitflies 
bob 1 17.52 0.001 bob, bobby, robert 

data = loadcsv('myfile.csv', delimiter='\t', parse_header=True, comment='#') 

Je voudrais être en mesure d'accéder aux données de deux façons:

  1. En tant que matrice Valeurs: il est important pour moi d'avoir un tableau numérique afin de pouvoir facilement transposer et accéder aux colonnes qui sont numériques. Dans ce cas, je veux être capable de faire quelque chose comme:

    floats_and_ints = data.matrix

    floats_and_ints[:, 0] # access the integers

    floats_and_ints[:, 1:3] # access some of the floats transpose(floats_and_ints) # etc..

  2. Comme un objet similaire à un dictionnaire où je n'ai pas savoir l'ordre des en-têtes: je souhaite également accéder aux données par ordre d'en-tête. Par exemple, je voudrais faire:

    data['favorite_float1'] # get all the values of the column with header "favorite_float1"

    data['name'] # get all the names of the rows

Je ne veux pas avoir de savoir que favorite_float1 est la deuxième colonne du tableau, car cela pourrait changer .

Il est également important pour moi de pouvoir parcourir les lignes et accéder aux champs par leur nom. Par exemple:

for row in data: 
    # print names and favorite integers of all 
    print "Name: ", row["name"], row["favorite_int"] 

La représentation (1) suggère un numpy.array, mais pour autant que je peux dire, cela ne traite pas correctement avec des chaînes et me demande de spécifier le type de données à l'avance et comme les étiquettes d'en-tête.

La représentation dans (2) suggère une liste de dictionnaires, et c'est ce que j'ai utilisé. Cependant, cela est vraiment mauvais pour les fichiers csv qui ont deux champs de chaîne mais le reste des colonnes sont numériques. Pour les valeurs numériques, vous voulez vraiment pouvoir accéder à la représentation matricielle et la manipuler en tant que numpy.array.

Existe-t-il une combinaison de fonctionnalités csv/numpy/scipy qui permet la flexibilité des deux mondes? Tout conseil sur ce sujet serait grandement apprécié.

En résumé, les principales caractéristiques sont les suivantes:

  1. capacité standard de spécifier délimiteurs, nombre de lignes à sauter, des colonnes à ignorer, etc.
  2. La possibilité d'obtenir un numpy.array/représentation matricielle des données de manière à pouvoir les valeurs numériques peuvent être manipulées
  3. la capacité d'extraire des colonnes et des lignes de nom d'en-tête (comme dans l'exemple ci-dessus)
+1

Euh, vous savez, ça ne me ressemble pas beaucoup ... – SamB

+1

Tout ce qui est écrit ci-dessus s'applique à n'importe quel fichier CSV/TSV. Les différences sont dans la façon dont le CSV/TSV est représenté - les deux types de représentations (liste de dicts, indexés par en-tête) et les représentations matricielles pour faciliter les manipulations de champs numériques sont utiles et j'aimerais un cadre qui me permette facilement de faire tous les deux. – user248237dfsf

Répondre

0

numpy.genfromtxt()

+3

Veuillez faire un lien vers les documents chaque fois que possible: http://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html – gotgenes

2

matplotlib.mlab.csv2rec retourne un numpyrecarray, de sorte que vous pouvez faire toutes les grandes choses numpy à ce que vous le feriez avec une gamme numpy. Les lignes individuelles, étant record cas, peuvent être indexés à tuples mais ont aussi des attributs nommés automatiquement pour les colonnes de vos données:

rows = matplotlib.mlab.csv2rec('data.csv') 
row = rows[0] 

print row[0] 
print row.name 
print row['name'] 

csv2rec comprend aussi « cité des chaînes », à la différence numpy.genfromtext. En général, je trouve que csv2rec combine certaines des meilleures caractéristiques de csv.reader et numpy.genfromtext.

4

Jetez un oeil à pandas qui est construit au-dessus de numpy. Voici un petit exemple:

In [7]: df = pd.read_csv('data.csv', sep='\t', index_col='name') 
In [8]: df 
Out[8]: 
     favorite_integer favorite_float1 favorite_float2  short_description 
name                    
johnny     5   60.20   0.520 johnny likes fruitflies 
bob     1   17.52   0.001  bob, bobby, robert 
In [9]: df.describe() 
Out[9]: 
     favorite_integer favorite_float1 favorite_float2 
count   2.000000   2.000000   2.000000 
mean   3.000000  38.860000   0.260500 
std   2.828427  30.179317   0.366988 
min   1.000000  17.520000   0.001000 
25%   2.000000  28.190000   0.130750 
50%   3.000000  38.860000   0.260500 
75%   4.000000  49.530000   0.390250 
max   5.000000  60.200000   0.520000 
In [13]: df.ix['johnny', 'favorite_integer'] 
Out[13]: 5 
In [15]: df['favorite_float1'] # or attribute: df.favorite_float1 
Out[15]: 
name 
johnny 60.20 
bob  17.52 
Name: favorite_float1 
In [16]: df['mean_favorite'] = df.mean(axis=1) 
In [17]: df.ix[:, 3:] 
Out[17]: 
       short_description mean_favorite 
name           
johnny johnny likes fruitflies  21.906667 
bob   bob, bobby, robert  6.173667 
0

Pourquoi ne pas simplement utiliser le csv.DictReader stdlib?