203 votes

Lire des colonnes spécifiques d'un fichier csv avec le module csv ?

J'essaie d'analyser un fichier csv et d'extraire les données de certaines colonnes seulement.

Exemple csv :

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | C... | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |

J'essaie de capturer uniquement des colonnes spécifiques, par exemple ID , Name , Zip et Phone .

Le code que j'ai regardé m'a conduit à croire que je peux appeler la colonne spécifique par son numéro correspondant, c'est-à-dire : Name correspondrait à 2 et en itérant à travers chaque ligne en utilisant row[2] produirait tous les éléments de la colonne 2. Mais ce n'est pas le cas.

Voici ce que j'ai fait jusqu'à présent :

import sys, argparse, csv
from settings import *

# command arguments
parser = argparse.ArgumentParser(description='csv to postgres',\
 fromfile_prefix_chars="@" )
parser.add_argument('file', help='csv file to import', action='store')
args = parser.parse_args()
csv_file = args.file

# open csv file
with open(csv_file, 'rb') as csvfile:

    # get number of columns
    for line in csvfile.readlines():
        array = line.split(',')
        first_item = array[0]

    num_columns = len(array)
    csvfile.seek(0)

    reader = csv.reader(csvfile, delimiter=' ')
        included_cols = [1, 2, 6, 7]

    for row in reader:
            content = list(row[i] for i in included_cols)
            print content

et je m'attends à ce que cela imprime uniquement les colonnes spécifiques que je veux pour chaque ligne, mais ce n'est pas le cas, je n'obtiens que la dernière colonne.

1 votes

pourquoi 'rb' pour open() ? cela ne devrait-il pas être simple r ?

7 votes

@Elazar : dans Python 2 (que l'OP utilise) "rb" est approprié pour être transmis à csv.reader .

0 votes

Pourquoi votre exemple de fichier CSV indique-t-il le caractère pipe comme délimiteur alors que votre exemple de code utilise un espace ?

218voto

Ryan Saxe Points 2664

La seule façon d'obtenir la dernière colonne de ce code est de ne pas inclure l'instruction d'impression. sur votre for boucle.

C'est très probablement la fin de votre code :

for row in reader:
    content = list(row[i] for i in included_cols)
print content

Tu veux que ce soit ça :

for row in reader:
        content = list(row[i] for i in included_cols)
        print content

Maintenant que nous avons couvert votre erreur, je voudrais profiter de ce moment pour vous présenter la pandas module.

Pandas est spectaculaire pour traiter les fichiers csv, et le code suivant serait tout ce dont vous avez besoin pour lire un csv et enregistrer une colonne entière dans une variable :

import pandas as pd
df = pd.read_csv(csv_file)
saved_column = df.column_name #you can also use df['column_name']

donc si tu voulais sauvegarder toutes les infos de ta colonne Names dans une variable, c'est tout ce que vous devez faire :

names = df.Names

C'est un excellent module et je vous suggère de l'examiner. Si pour une raison quelconque, votre instruction d'impression était dans for et il n'imprimait toujours que la dernière colonne, ce qui ne devrait pas arriver, mais faites-moi savoir si mon hypothèse était fausse. Le code que vous avez posté comporte de nombreuses erreurs d'indentation, il était donc difficile de savoir ce qui devait être à sa place. J'espère que cela a été utile !

1 votes

Est-il possible de supprimer les numéros d'index de la requête ? @Ryan Saxe

0 votes

Oui, il suffit d'itérer à travers elle dans une boucle for.

0 votes

"Maintenant que nous avons couvert votre erreur, je voudrais profiter de ce moment pour vous présenter le module pandas." Ah, oui, vous ne faites pas du Python tant que vous n'avez pas utilisé Pandas !

125voto

HennyH Points 4731
import csv
from collections import defaultdict

columns = defaultdict(list) # each value in each column is appended to a list

with open('file.txt') as f:
    reader = csv.DictReader(f) # read rows into a dictionary format
    for row in reader: # read a row as {column1: value1, column2: value2,...}
        for (k,v) in row.items(): # go over each column name and value 
            columns[k].append(v) # append the value into the appropriate list
                                 # based on column name k

print(columns['name'])
print(columns['phone'])
print(columns['street'])

Avec un fichier comme

name,phone,street
Bob,0893,32 Silly
James,000,400 McHilly
Smithers,4442,23 Looped St.

La sortie sera

>>> 
['Bob', 'James', 'Smithers']
['0893', '000', '4442']
['32 Silly', '400 McHilly', '23 Looped St.']

Ou encore, si vous souhaitez une indexation numérique des colonnes :

with open('file.txt') as f:
    reader = csv.reader(f)
    reader.next()
    for row in reader:
        for (i,v) in enumerate(row):
            columns[i].append(v)
print(columns[0])

>>> 
['Bob', 'James', 'Smithers']

Pour changer le délimiteur, ajoutez delimiter=" " à l'instanciation appropriée, c'est-à-dire reader = csv.reader(f,delimiter=" ")

32voto

Vasya Novikov Points 1670

Utilisez pandas :

import pandas as pd
my_csv = pd.read_csv(filename)
column = my_csv.column_name
# you can also use my_csv['column_name']

Suppression des colonnes inutiles au moment de l'analyse :

my_filtered_csv = pd.read_csv(filename, usecols=['col1', 'col3', 'col7'])

P.S. Je ne fais que rassembler ce que les autres ont dit de manière simple. Les réponses réelles sont tirées de ici et ici .

1 votes

Je pense que Pandas est une solution parfaitement acceptable. J'utilise souvent Pandas et j'aime beaucoup cette bibliothèque, mais cette question faisait spécifiquement référence au module CSV.

1 votes

@frankV Eh bien, le titre, les balises et le premier paragraphe n'interdisent en aucun cas les pandas, comme je peux le constater. En fait, j'espérais juste ajouter une réponse plus simple à celles déjà faites ici (les autres réponses utilisent aussi des pandas).

21voto

G M Points 508

Vous pouvez utiliser numpy.loadtext(filename) . Par exemple, si votre base de données est la suivante .csv :

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | Adam | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
10 | Carl | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
10 | Adolf | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
10 | Den | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |

Et vous voulez le Name colonne :

import numpy as np 
b=np.loadtxt(r'filepath\name.csv',dtype=str,delimiter='|',skiprows=1,usecols=(1,))

>>> b
array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
      dtype='|S7')

Vous pouvez utiliser plus facilement genfromtext :

b = np.genfromtxt(r'filepath\name.csv', delimiter='|', names=True,dtype=None)
>>> b['Name']
array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
      dtype='|S7')

0 votes

Est-ce qu'il doit y avoir un r à côté de "filepath" ? \name.csv ' ?

19voto

ayhan Points 33889

Avec pandas vous pouvez utiliser read_csv avec usecols paramètre :

df = pd.read_csv(filename, usecols=['col1', 'col3', 'col7'])

Exemple :

import pandas as pd
import io

s = '''
total_bill,tip,sex,smoker,day,time,size
16.99,1.01,Female,No,Sun,Dinner,2
10.34,1.66,Male,No,Sun,Dinner,3
21.01,3.5,Male,No,Sun,Dinner,3
'''

df = pd.read_csv(io.StringIO(s), usecols=['total_bill', 'day', 'size'])
print(df)

   total_bill  day  size
0       16.99  Sun     2
1       10.34  Sun     3
2       21.01  Sun     3

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