Python importa CSV nella lista


194

Ho un file CSV con circa 2000 record.

Ogni record ha una stringa e una categoria:

This is the first line,Line1
This is the second line,Line2
This is the third line,Line3

Devo leggere questo file in un elenco simile al seguente:

data = [('This is the first line', 'Line1'),
        ('This is the second line', 'Line2'),
        ('This is the third line', 'Line3')]

Come posso importare questo CSV nell'elenco di cui ho bisogno usando Python?


2
Quindi utilizzare il csvmodulo: docs.python.org/2/library/csv.html
furas

4
Se esiste una risposta adatta alla tua domanda, accettala.
Maciej Gol,

Risposte:


308

Utilizzando il modulo CSV :

import csv

with open('file.csv', newline='') as f:
    reader = csv.reader(f)
    data = list(reader)

print(data)

Produzione:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]

Se hai bisogno di tuple:

import csv

with open('file.csv', newline='') as f:
    reader = csv.reader(f)
    data = [tuple(row) for row in reader]

print(data)

Produzione:

[('This is the first line', 'Line1'), ('This is the second line', 'Line2'), ('This is the third line', 'Line3')]

Vecchia risposta Python 2, anche usando il csvmodulo:

import csv
with open('file.csv', 'rb') as f:
    reader = csv.reader(f)
    your_list = list(reader)

print your_list
# [['This is the first line', 'Line1'],
#  ['This is the second line', 'Line2'],
#  ['This is the third line', 'Line3']]

4
Perché usi 'rb' invece di 'r'?
imrek,

5
@DrunkenMaster, bfa sì che il file venga aperto in modalità binaria anziché in modalità testo. In alcuni sistemi la modalità testo significa che \ndurante la lettura o la scrittura verranno convertiti in nuove righe specifiche della piattaforma. Vedi documenti .
Maciej Gol,

7
Questo non funziona in Python 3.x: "csv.Error: iteratore dovrebbe restituire stringhe, non byte (hai aperto il file in modalità testo?)" Vedi sotto per la risposta che funziona in Python 3.x
Gilbert

2
per risparmiare qualche secondo di tempo nel debug, dovresti probabilmente aggiungere una nota per la prima soluzione, come "Python 2.x versione"
paradite

Come usare la tua prima soluzione ma con solo alcune colonne del file CSV?
Sigur,

54

Aggiornato per Python 3 :

import csv

with open('file.csv', newline='') as f:
    reader = csv.reader(f)
    your_list = list(reader)

print(your_list)

Produzione:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]

Specificare 'r'è la modalità predefinita, quindi non è necessario specificarla. I documenti menzionano anche Se csvfile è un oggetto file, dovrebbe essere aperto con newline = ''.
AMC

44

Panda è piuttosto bravo a gestire i dati. Ecco un esempio su come usarlo:

import pandas as pd

# Read the CSV into a pandas data frame (df)
#   With a df you can do many things
#   most important: visualize data with Seaborn
df = pd.read_csv('filename.csv', delimiter=',')

# Or export it in many ways, e.g. a list of tuples
tuples = [tuple(x) for x in df.values]

# or export it as a list of dicts
dicts = df.to_dict().values()

Un grande vantaggio è che i panda si occupano automaticamente delle righe di intestazione.

Se non ne hai sentito parlare Seaborn , ti consiglio di dare un'occhiata.

Guarda anche: Come posso leggere e scrivere file CSV con Python?

Panda # 2

import pandas as pd

# Get data - reading the CSV file
import mpu.pd
df = mpu.pd.example_df()

# Convert
dicts = df.to_dict('records')

Il contenuto di df è:

     country   population population_time    EUR
0    Germany   82521653.0      2016-12-01   True
1     France   66991000.0      2017-01-01   True
2  Indonesia  255461700.0      2017-01-01  False
3    Ireland    4761865.0             NaT   True
4      Spain   46549045.0      2017-06-01   True
5    Vatican          NaN             NaT   True

Il contenuto di dicts è

[{'country': 'Germany', 'population': 82521653.0, 'population_time': Timestamp('2016-12-01 00:00:00'), 'EUR': True},
 {'country': 'France', 'population': 66991000.0, 'population_time': Timestamp('2017-01-01 00:00:00'), 'EUR': True},
 {'country': 'Indonesia', 'population': 255461700.0, 'population_time': Timestamp('2017-01-01 00:00:00'), 'EUR': False},
 {'country': 'Ireland', 'population': 4761865.0, 'population_time': NaT, 'EUR': True},
 {'country': 'Spain', 'population': 46549045.0, 'population_time': Timestamp('2017-06-01 00:00:00'), 'EUR': True},
 {'country': 'Vatican', 'population': nan, 'population_time': NaT, 'EUR': True}]

Panda # 3

import pandas as pd

# Get data - reading the CSV file
import mpu.pd
df = mpu.pd.example_df()

# Convert
lists = [[row[col] for col in df.columns] for row in df.to_dict('records')]

Il contenuto di listsè:

[['Germany', 82521653.0, Timestamp('2016-12-01 00:00:00'), True],
 ['France', 66991000.0, Timestamp('2017-01-01 00:00:00'), True],
 ['Indonesia', 255461700.0, Timestamp('2017-01-01 00:00:00'), False],
 ['Ireland', 4761865.0, NaT, True],
 ['Spain', 46549045.0, Timestamp('2017-06-01 00:00:00'), True],
 ['Vatican', nan, NaT, True]]

tuples = [tuple(x) for x in df.values]può essere scritto tuples = list(df.itertuples(index=False))invece. Nota che i documenti di Pandas scoraggiano l'uso .valuesin favore di .to_numpy(). Il terzo esempio mi confonde. Innanzitutto, perché la variabile è denominata tuples, il che implicherebbe che è un elenco di tuple, mentre in realtà è un elenco di elenchi. In secondo luogo, perché per quanto ne so, l'intera espressione può essere sostituita con df.to_list(). Inoltre non so se il secondo esempio è davvero rilevante qui.
AMC

9

Aggiornamento per Python3:

import csv
from pprint import pprint

with open('text.csv', newline='') as file:
    reader = csv.reader(file)
    res = list(map(tuple, reader))

pprint(res)

Produzione:

[('This is the first line', ' Line1'),
 ('This is the second line', ' Line2'),
 ('This is the third line', ' Line3')]

Se csvfile è un oggetto file, dovrebbe essere aperto con newline=''.
modulo csv


Perché usare list(map())oltre la comprensione di un elenco? Inoltre, nota lo spazio bianco all'inizio di ogni elemento della seconda colonna.
AMC

5

Se sei sicuro che non ci sono le virgole nel ingresso, diverso da quello di separare la categoria, è possibile leggere il file riga per riga e dividere su ,, quindi spingere il risultatoList

Detto questo, sembra che tu stia guardando un file CSV, quindi potresti prendere in considerazione l'utilizzo dei moduli per esso


4
result = []
for line in text.splitlines():
    result.append(tuple(line.split(",")))

1
Potete per favore aggiungere un po 'di spiegazione a questo post? Solo il codice è (a volte) buono, ma il codice e la spiegazione sono (la maggior parte delle volte) migliori
Barranka

3
So che il commento di Barranka ha più di un anno, ma per tutti quelli che si imbattono in questo e non riescono a capirlo: for line in text.splitlines (): mette ogni singola riga nella variabile temp "line". line.split (",") crea un elenco di stringhe che sono divise sulla virgola. tuple (~) inserisce tale elenco in una tupla e append (~) lo aggiunge al risultato. Dopo il ciclo, risultato è un elenco di tuple, con ciascuna tupla una linea e ogni elemento tupla un elemento nel file CSV.
Louis,

Oltre a ciò che ha detto @Louis, non è necessario utilizzare .read().splitlines(), è possibile scorrere direttamente su ciascuna riga del file: for line in in_file: res.append(tuple(line.rstrip().split(",")))Inoltre, si noti che l'utilizzo .split(',')significa che ogni elemento della seconda colonna inizierà con uno spazio aggiuntivo.
AMC

Addendum al codice che ho appena condiviso sopra: line.rstrip()-> line.rstrip('\n').
AMC

3

Come già detto nei commenti, puoi usare la csvlibreria in Python. CSV significa valori separati da virgola che sembra esattamente il tuo caso: un'etichetta e un valore separati da una virgola.

Essendo una categoria e un tipo di valore, preferirei utilizzare un tipo di dizionario anziché un elenco di tuple.

Comunque nel codice qui sotto mostro entrambi i modi: dè il dizionario ed lè l'elenco delle tuple.

import csv

file_name = "test.txt"
try:
    csvfile = open(file_name, 'rt')
except:
    print("File not found")
csvReader = csv.reader(csvfile, delimiter=",")
d = dict()
l =  list()
for row in csvReader:
    d[row[1]] = row[0]
    l.append((row[0], row[1]))
print(d)
print(l)

Perché non utilizzare un gestore di contesto per gestire il file? Perché stai mescolando due diverse convenzioni di denominazione variabile? Non è (row[0], row[1])più debole / più soggetto a errori rispetto al semplice utilizzo tuple(row)?
AMC

Perché pensi che fare tupla (riga) sia meno soggetto a errori? A quale convenzione di denominazione variabile ti riferisci? Collega una convenzione ufficiale di denominazione in pitone. Per quanto ne so, provare -except è un buon modo per gestire i file: cosa intendi per gestore del contesto?
Francesco Boi,

Perché pensi che fare tupla (riga) sia meno soggetto a errori? Perché non richiede di scrivere manualmente ogni singolo indice. Se si commette un errore o il numero di elementi cambia, è necessario tornare indietro e modificare il codice. Try-tranne va bene, i gestori di contesto sono l'istruzione with. Puoi trovare molte risorse sull'argomento, come questo .
AMC

Non vedo come il gestore del contesto sarebbe migliore del vecchio buon blocco try-tranne. Per l'altro, l'aspetto positivo è che si digita meno codice; per il resto se il numero di elementi (suppongo tu intenda il numero di colonne) cambia il mio è meglio perché sta estraendo solo i valori desiderati mentre l'altro sta estraendo tutto l'eccellenza. Senza alcun requisito specifico non si può dire quale sia la migliore, quindi è una perdita di tempo discutere quale sia la migliore: in questo caso entrambi sono validi
Francesco Boi

Non vedo come il gestore del contesto sarebbe migliore del vecchio buon blocco try-tranne. Si prega di vedere il mio commento precedente, il gestore del contesto non sostituisce la prova-tranne.
AMC

2

Un semplice ciclo sarebbe sufficiente:

lines = []
with open('test.txt', 'r') as f:
    for line in f.readlines():
        l,name = line.strip().split(',')
        lines.append((l,name))

print lines

1
Cosa succede se alcune voci presentano delle virgole?
Tony Ennis,

@TonyEnnis Quindi è necessario utilizzare un ciclo di elaborazione più avanzato. La risposta di Maciej sopra mostra come usare il parser CSV fornito con Python per eseguire questa operazione. Molto probabilmente questo parser ha tutta la logica di cui hai bisogno.
Hunter McMillen,

1

Purtroppo nessuna delle risposte esistenti è particolarmente soddisfacente.

Ecco una soluzione Python 3 semplice e completa, usando il modulo CSV .

import csv

with open('../resources/temp_in.csv', newline='') as f:
    reader = csv.reader(f, skipinitialspace=True)
    rows = list(reader)

print(rows)

Nota l' skipinitialspace=Trueargomento. Ciò è necessario poiché, purtroppo, il CSV di OP contiene spazi bianchi dopo ogni virgola.

Produzione:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]

0

Estendendo un po 'le tue esigenze e supponendo che non ti interessi l'ordine delle linee e desideri raggrupparle in categorie, la seguente soluzione potrebbe funzionare per te:

>>> fname = "lines.txt"
>>> from collections import defaultdict
>>> dct = defaultdict(list)
>>> with open(fname) as f:
...     for line in f:
...         text, cat = line.rstrip("\n").split(",", 1)
...         dct[cat].append(text)
...
>>> dct
defaultdict(<type 'list'>, {' CatA': ['This is the first line', 'This is the another line'], ' CatC': ['This is the third line'], ' CatB': ['This is the second line', 'This is the last line']})

In questo modo ottieni tutte le righe pertinenti disponibili nel dizionario sotto la categoria chiave.


0

Ecco il modo più semplice in Python 3.x di importare un CSV in un array multidimensionale e le sue sole 4 righe di codice senza importare nulla!

#pull a CSV into a multidimensional array in 4 lines!

L=[]                            #Create an empty list for the main array
for line in open('log.txt'):    #Open the file and read all the lines
    x=line.rstrip()             #Strip the \n from each line
    L.append(x.split(','))      #Split each line into a list and add it to the
                                #Multidimensional array
print(L)

Fai attenzione, è un elenco, non un array! Perché non utilizzare un gestore di contesto per gestire correttamente l'oggetto file? Si noti che questa soluzione lascia spazi bianchi extra sul secondo elemento in ogni riga e che non riuscirà se uno qualsiasi dei dati contiene una virgola.
AMC

-1

Il prossimo è un pezzo di codice che utilizza il modulo CSV ma estrae i contenuti di file.csv in un elenco di dicts usando la prima riga che è un'intestazione della tabella CSV

import csv
def csv2dicts(filename):
  with open(filename, 'rb') as f:
    reader = csv.reader(f)
    lines = list(reader)
    if len(lines) < 2: return None
    names = lines[0]
    if len(names) < 1: return None
    dicts = []
    for values in lines[1:]:
      if len(values) != len(names): return None
      d = {}
      for i,_ in enumerate(names):
        d[names[i]] = values[i]
      dicts.append(d)
    return dicts
  return None

if __name__ == '__main__':
  your_list = csv2dicts('file.csv')
  print your_list

1
Perché non usare solo csv.DictReader?
AMC
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.