web-dev-qa-db-fra.com

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

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

Exemple csv:

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

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

Le code que j'ai consulté m'a amené à croire que je peux appeler la colonne spécifique par son numéro correspondant. Ainsi: Name correspondrait à 2 et une itération dans chaque ligne à l'aide de row[2] générerait tous les éléments de la colonne 2. Seulement t.

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 n'imprimera que les colonnes spécifiques que je veux pour chaque ligne, sauf que ce n'est pas le cas, je reçois uniquement la dernière colonne.

130
frankV

Si vous n'incluez pas votre instruction print in votre boucle for, la seule façon d'obtenir la dernière colonne de ce code est de ne pas inclure votre instruction print. 

C'est probablement la fin de votre code:

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

Vous voulez que ce soit ceci:

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 cette occasion pour vous présenter le module pandas .

Les pandas sont spectaculaires pour traiter les fichiers csv, et le code suivant suffirait 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 vous voulez enregistrer toutes les informations de votre colonne Names dans une variable, vous n'avez plus qu'à:

names = df.Names

C'est un excellent module et je vous suggère de l'examiner. Si, pour une raison quelconque, votre instruction print était dans la boucle for et si elle imprimait toujours la dernière colonne, cela ne devrait pas arriver, mais laissez-moi savoir si ma supposition était fausse. Votre code posté contient beaucoup d'erreurs d'indentation, il était donc difficile de savoir où était supposé se trouver. J'espère que cela a été utile!

147
Ryan Saxe
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.

Sortie

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

Ou bien 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éliminateur, ajoutez delimiter=" " à l’instanciation appropriée, par exemple reader = csv.reader(f,delimiter=" ").

91
HennyH

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']

Jeter les colonnes inutiles au moment de l'analyse:

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

P.S. Je suis simplement en train d'agréger ce que les autres ont dit d'une manière simple. Les réponses réelles sont tirées de ici et ici .

16
VasiliNovikov

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

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
13
ayhan

Vous pouvez utiliser numpy.loadtext(filename). Par exemple, s'il s'agit de votre base de données .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 la colonne Name:

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')

Plus facilement, vous pouvez utiliser genfromtext:

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

Contexte: Pour ce type de travail, vous devriez utiliser l'incroyable bibliothèque python petl. Cela vous évitera beaucoup de travail et la frustration potentielle de faire les choses «manuellement» avec le module CSV standard. Selon les informations dont je dispose, les seules personnes qui utilisent encore le module csv sont celles qui n’ont pas encore découvert de meilleurs outils pour travailler avec des données tabulaires (pandas, petl, etc.), ce qui est correct, mais si vous envisagez de travailler avec beaucoup de données votre carrière à partir de sources diverses et étranges, apprendre quelque chose comme petl est l’un des meilleurs investissements que vous puissiez faire. Pour commencer, ne prenez que 30 minutes après l’installation de pip. La documentation est excellente.

Réponse: Supposons que vous ayez la première table dans un fichier csv (vous pouvez aussi charger directement depuis la base de données en utilisant petl). Ensuite, il vous suffira de le charger et de procéder comme suit.

from petl import fromcsv, look, cut, tocsv 

#Load the table
table1 = fromcsv('table1.csv')
# Alter the colums
table2 = cut(table1, 'Song_Name','Artist_ID')
#have a quick look to make sure things are ok. Prints a nicely formatted table to your console
print look(table2)
# Save to new file
tocsv(table2, 'new.csv')
4
PeteBeat
import pandas as pd 
csv_file = pd.read_csv("file.csv") 
column_val_list = csv_file.column_name._ndarray_values
1
Hari K

Pour récupérer nom de la colonne , au lieu d’utiliser readlines () better use readline () afin d’éviter la lecture en boucle du fichier complet et son stockage dans le tableau.

with open(csv_file, 'rb') as csvfile:

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
0
Suren

Si vous devez traiter les colonnes séparément, j'aime bien déstructurer les colonnes avec le modèle Zip(*iterable) (en fait, "décompresser"). Donc, pour votre exemple:

ids, names, zips, phones = Zip(*(
  (row[1], row[2], row[6], row[7])
  for row in reader
))
0
Robert Jensen

Grâce à la manière dont vous pouvez indexer et sous-définir un cadre de données pandas, il est très facile d'extraire une colonne unique d'un fichier csv dans une variable:

myVar = pd.read_csv('YourPath', sep = ",")['ColumnName']

Quelques points à considérer:

L'extrait ci-dessus produira un pandas Series et non dataframe. La suggestion de ayhan avec usecols sera également plus rapide si la vitesse est un problème . Tester les deux approches différentes en utilisant %timeit sur un fichier csv de 2122 Ko donne 22.8 ms pour l’approche usecols et 53 ms pour l’approche suggérée.

Et n'oubliez pas import pandas as pd

0
vestland