Leggi colonne specifiche da un file CSV con modulo CSV?


176

Sto cercando di analizzare un file CSV ed estrarre i dati solo da colonne specifiche.

Esempio di CSV:

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

Sto cercando di catturare solo le colonne specifiche, ad esempio ID, Name, Zipe Phone.

Il codice che ho visto mi ha portato a credere di poter chiamare la colonna specifica per il suo numero corrispondente, quindi vale a dire: Namecorrisponderebbe 2e ripetendo ogni riga usando row[2]produrrebbe tutti gli elementi nella colonna 2. Solo che non lo fa.

Ecco cosa ho fatto finora:

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

e mi aspetto che questo stamperà solo le colonne specifiche che desidero per ogni riga, tranne per il fatto che ottengo solo l'ultima colonna.


1
perché 'rb'bandiera a open()? non dovrebbe essere semplice r?
Elazar,

7
@Elazar: in Python 2 (che utilizza l'OP) "rb"è appropriato per il passaggio csv.reader.
DSM,

Perché il tuo file CSV di esempio mostra il carattere pipe come delimitatore ma il tuo codice di esempio utilizza uno spazio?
Kelly S. francese,

1
@ KellyS.French Ho pensato che avrebbe aiutato a visualizzare i dati ai fini di questa domanda.
franco,

Risposte:


187

L'unico modo per ottenere l'ultima colonna da questo codice è se non includi la tua dichiarazione di stampa nel tuo forciclo.

Questa è probabilmente la fine del tuo codice:

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

Vuoi che sia questo:

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

Ora che abbiamo coperto il tuo errore, vorrei dedicare questo tempo a presentarti il modulo Panda .

Panda è spettacolare per gestire i file CSV e il seguente codice sarebbe tutto ciò che serve per leggere un CSV e salvare un'intera colonna in una variabile:

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

quindi se vuoi salvare tutte le informazioni nella tua colonna Namesin una variabile, questo è tutto ciò che devi fare:

names = df.Names

È un modulo eccezionale e ti suggerisco di esaminarlo. Se per qualche motivo la tua dichiarazione di stampa fosse in forloop e continuasse a stampare solo l'ultima colonna, il che non dovrebbe accadere, ma fammi sapere se la mia ipotesi era errata. Il tuo codice pubblicato presenta molti errori di rientro, quindi era difficile sapere che cosa doveva essere dove. Spero sia stato utile!


1
È possibile rimuovere i numeri di indice dalla query? @Ryan Saxe
Malachi Bazar

Sì, basta scorrere attraverso di esso in un ciclo for.
davegallant,

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

Con un file come

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

Verrà emesso

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

O in alternativa se si desidera l'indicizzazione numerica per le colonne:

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

Per modificare il deliminatore aggiungere all'istanza delimiter=" "appropriata, ad esreader = csv.reader(f,delimiter=" ")


30

Usa i panda :

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

Elimina le colonne non necessarie al momento dell'analisi:

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

PS Sto solo aggregando ciò che gli altri hanno detto in modo semplice. Le risposte effettive sono prese da qui e qui .


1
Penso che Panda sia una soluzione perfettamente accettabile. Uso spesso i panda e mi piace molto la libreria, ma questa domanda fa specifico riferimento al modulo CSV.
francia,

1
@frankV Bene, il titolo, i tag e il primo paragrafo non vietano in alcun modo i panda, AFAI può vedere. In realtà ho solo sperato di aggiungere una risposta più semplice a quelle già fatte qui (altre risposte usano anche i panda).
VasiliNovikov,

18

Con i panda puoi usare read_csvcon il usecolsparametro:

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

Esempio:

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

16

È possibile utilizzare numpy.loadtext(filename). Ad esempio se questo è il tuo database .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 |

E vuoi la Namecolonna:

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

Più facilmente puoi usare genfromtext:

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

@G C'è un r accanto a 'filepath \ name.csv'?
114

6

Contesto: per questo tipo di lavoro dovresti usare la straordinaria libreria petl di Python. Ciò ti farà risparmiare un sacco di lavoro e potenziale frustrazione nel fare le cose "manualmente" con il modulo CSV standard. AFAIK, le uniche persone che usano ancora il modulo CSV sono quelle che non hanno ancora scoperto strumenti migliori per lavorare con dati tabulari (panda, petl, ecc.), Il che va bene, ma se prevedi di lavorare con molti dati in la tua carriera da varie strane fonti, imparare qualcosa come petl è uno dei migliori investimenti che puoi fare. Per iniziare, dovrebbero essere necessari solo 30 minuti dopo aver completato l'installazione di pip petl. La documentazione è eccellente

Risposta: Supponiamo che tu abbia la prima tabella in un file CSV (puoi anche caricare direttamente dal database usando petl). Quindi lo caricheresti semplicemente e farai quanto segue.

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

Penso che ci sia un modo più semplice

import pandas as pd

dataset = pd.read_csv('table1.csv')
ftCol = dataset.iloc[:, 0].values

Quindi qui iloc[:, 0], :significa tutti i valori, 0indica la posizione della colonna. nell'esempio che segue IDverrà selezionato

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

Se funziona ragazzi, per favore, fate sapere agli altri :)
Nuriddin Kudratov,

3
import pandas as pd 
csv_file = pd.read_csv("file.csv") 
column_val_list = csv_file.column_name._ndarray_values

Dovrai pip install pandasprima
Boris il

1

Grazie al modo in cui è possibile indicizzare e sottoinsieme un frame di dati Panda, un modo molto semplice per estrarre una singola colonna da un file CSV in una variabile è:

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

Alcune cose da considerare:

Lo snippet qui sopra produrrà un panda Seriese non dataframe. Il suggerimento di ayhan con usecolssarà anche più veloce se la velocità è un problema. Testare i due diversi approcci usando %timeitun file csv di dimensioni 2122 KB produce 22.8 msper l'approccio usecols e 53 msper il mio approccio suggerito.

E non dimenticare import pandas as pd


0

Se hai bisogno di elaborare le colonne separatamente, mi piace distruggere le colonne con il zip(*iterable)modello (effettivamente "decomprimere"). Quindi, per il tuo esempio:

ids, names, zips, phones = zip(*(
  (row[1], row[2], row[6], row[7])
  for row in reader
))

-1

Per recuperare il nome della colonna , anziché utilizzare readlines (), utilizzare meglio readline () per evitare il ciclo, la lettura del file completo e la sua memorizzazione nell'array.

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

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.