Python importiert CSV in Liste

192

Ich habe eine CSV-Datei mit ungefähr 2000 Datensätzen.

Jeder Datensatz hat eine Zeichenfolge und eine Kategorie:

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

Ich muss diese Datei in eine Liste einlesen, die so aussieht:

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

Wie kann ich diese CSV mit Python in die Liste importieren, die ich benötige?

MorganTN
quelle
2
Verwenden Sie dann das csvModul: docs.python.org/2/library/csv.html
furas
4
Wenn es eine Antwort gibt, die zu Ihrer Frage passt, akzeptieren Sie diese bitte.
Maciej Gol
1
Mögliches Duplikat von Wie lese und schreibe ich CSV-Dateien mit Python?
Martin Thoma

Antworten:

304

Verwenden des CSV-Moduls :

import csv

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

print(data)

Ausgabe:

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

Wenn Sie Tupel benötigen:

import csv

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

print(data)

Ausgabe:

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

Alte Python 2-Antwort, auch mit dem csvModul:

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']]
Maciej Gol
quelle
4
Warum benutzt du 'rb' anstelle von 'r'?
Imrek
5
@DrunkenMaster bbewirkt , dass die Datei im Binärmodus und nicht im Textmodus geöffnet wird. Auf einigen Systemen bedeutet der Textmodus, dass er \nbeim Lesen oder Schreiben in eine plattformspezifische neue Zeile konvertiert wird. Siehe Dokumente .
Maciej Gol
7
Dies funktioniert in Python 3.x nicht: "csv.Error: Der Iterator sollte Zeichenfolgen und keine Bytes zurückgeben (haben Sie die Datei im Textmodus geöffnet?)" Die Antwort, die in Python 3.x funktioniert
Gilbert
2
Um ein paar Sekunden Zeit beim Debuggen zu sparen, sollten Sie wahrscheinlich einen Hinweis für die erste Lösung hinzufügen, wie "Python 2.x Version"
Paradite
Wie verwende ich meine erste Lösung, aber nur mit einigen Spalten aus der CSV-Datei?
Sigur
54

Aktualisiert für Python 3 :

import csv

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

print(your_list)

Ausgabe:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]
Seokhoonlee
quelle
Die Angabe 'r'ist der Standardmodus, daher ist die Angabe nicht erforderlich . In den Dokumenten wird auch erwähnt, dass csvfile ein Dateiobjekt ist, das mit newline = '' geöffnet werden sollte.
AMC
43

Pandas kann ziemlich gut mit Daten umgehen . Hier ist ein Beispiel für die Verwendung:

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

Ein großer Vorteil ist, dass Pandas automatisch mit Kopfzeilen umgehen.

Wenn Sie noch nichts von Seaborn gehört haben , empfehle ich Ihnen , es sich anzusehen.

Siehe auch: Wie lese und schreibe ich CSV-Dateien mit Python?

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

Der Inhalt von df ist:

     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

Der Inhalt von Diktaten ist

[{'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}]

Pandas # 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')]

Der Inhalt von listsist:

[['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]]
Martin Thoma
quelle
tuples = [tuple(x) for x in df.values]kann stattdessen geschrieben tuples = list(df.itertuples(index=False))werden. Beachten Sie, dass die Pandas-Dokumente von der Verwendung .valueszugunsten von abraten .to_numpy(). Das dritte Beispiel ist für mich verwirrend. Erstens, weil die Variable benannt ist tuples, was bedeuten würde, dass es sich um eine Liste von Tupeln handelt, während es sich tatsächlich um eine Liste von Listen handelt. Zweitens, weil, soweit ich das beurteilen kann, der gesamte Ausdruck durch ersetzt werden kann df.to_list(). Ich weiß auch nicht, ob das zweite Beispiel hier wirklich relevant ist.
AMC
9

Update für 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)

Ausgabe:

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

Wenn csvfile ein Dateiobjekt ist, sollte es mit geöffnet werden newline=''.
CSV-Modul

Infinitesimalrechnung
quelle
Warum list(map())über ein Listenverständnis verwenden? Beachten Sie auch das Leerzeichen am Anfang jedes Elements der zweiten Spalte.
AMC
5

Wenn Sie sicher , es gibt keine Kommas in Ihrem Eingang, andere als die Kategorie zu trennen, können Sie die Datei Zeile für Zeile gelesen und aufgeteilt auf ,, und drücken Sie dann das Ergebnis anList

Es sieht jedoch so aus, als würden Sie sich eine CSV-Datei ansehen. Sie könnten also in Betracht ziehen, die Module dafür zu verwenden

Miquel
quelle
4
result = []
for line in text.splitlines():
    result.append(tuple(line.split(",")))
Acid_Snake
quelle
1
Können Sie diesem Beitrag bitte eine Erklärung hinzufügen? Nur Code ist (manchmal) gut, aber Code und Erklärung sind (meistens) besser
Barranka
3
Ich weiß, dass Barrankas Kommentar über ein Jahr alt ist, aber für jeden, der darauf stößt und es nicht herausfinden kann: für Zeile in text.splitlines (): Setzt jede einzelne Zeile in die temporäre Variable "Zeile". line.split (",") erstellt eine Liste von Zeichenfolgen, die im Komma aufgeteilt sind. Tupel (~) legt die Liste in einem Tupel und append (~) fügt sie das Ergebnis. Nach der Schleife ist das Ergebnis eine Liste von Tupeln, wobei jedes Tupel eine Zeile und jedes Tupelelement ein Element in der CSV-Datei ist.
Louis
Zusätzlich zu den Aussagen von @Louis ist keine Verwendung erforderlich .read().splitlines(). Sie können jede Zeile der Datei direkt durchlaufen: for line in in_file: res.append(tuple(line.rstrip().split(",")))Beachten Sie außerdem, dass using .split(',')bedeutet, dass jedes Element der zweiten Spalte mit einem zusätzlichen Leerzeichen beginnt.
AMC
Nachtrag zu dem Code, den ich gerade oben geteilt habe: line.rstrip()-> line.rstrip('\n').
AMC
3

Wie bereits in den Kommentaren erwähnt, können Sie die csvBibliothek in Python verwenden. csv bedeutet durch Kommas getrennte Werte, was genau Ihr Fall zu sein scheint: eine Beschriftung und ein durch Komma getrennter Wert.

Als Kategorie- und Wertetyp würde ich lieber einen Wörterbuchtyp anstelle einer Liste von Tupeln verwenden.

Wie auch immer, im folgenden Code zeige ich beide Möglichkeiten: dist das Wörterbuch und list die Liste der Tupel.

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)
Francesco Boi
quelle
Warum nicht einen Kontextmanager verwenden, um die Datei zu verarbeiten? Warum mischen Sie zwei verschiedene Namenskonventionen für Variablen? Ist nicht (row[0], row[1])schwächer / fehleranfälliger als nur zu verwenden tuple(row)?
AMC
Warum ist Tupel (Zeile) Ihrer Meinung nach weniger fehleranfällig? Auf welche Konvention zur Benennung von Variablen beziehen Sie sich? Bitte verlinken Sie eine offizielle Python-Namenskonvention. Soweit ich weiß, ist try -except eine gute Möglichkeit, mit Dateien umzugehen: Was meinst du mit Context Handler?
Francesco Boi
Warum denkst du, ist Tupel (Zeile) weniger fehleranfällig? Weil es nicht erforderlich ist, dass Sie jeden einzelnen Index manuell ausschreiben. Wenn Sie einen Fehler machen oder sich die Anzahl der Elemente ändert, müssen Sie zurückgehen und Ihren Code ändern. Das Try-Except ist in Ordnung, Kontextmanager sind die with-Anweisung. Sie können viele Ressourcen zu diesem Thema finden, wie diese .
AMC
Ich sehe nicht ein, wie der Kontextmanager besser wäre als der alte gute Try-Except-Block. Zum anderen ist der positive Aspekt, dass Sie weniger Code eingeben; Im Übrigen ist es besser, wenn sich die Anzahl der Elemente (ich denke du meinst die Anzahl der Spalten) ändert, da nur die gewünschten Werte extrahiert werden, während das andere das gesamte Excel extrahiert. Ohne eine bestimmte Anforderung kann man nicht sagen, was besser ist, daher ist es Zeitverschwendung, darüber zu streiten, was besser ist: In diesem Fall sind beide gültig
Francesco Boi
Ich sehe nicht ein, wie der Kontextmanager besser wäre als der alte gute Try-Except-Block. Bitte beachten Sie meinen vorherigen Kommentar, der Kontextmanager würde den Versuch nicht ersetzen , außer.
AMC
2

Eine einfache Schleife würde ausreichen:

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

print lines
Hunter McMillen
quelle
1
Was ist, wenn einige Einträge Kommas enthalten?
Tony Ennis
@TonyEnnis Dann müssten Sie eine erweiterte Verarbeitungsschleife verwenden. Die Antwort von Maciej oben zeigt, wie der mit Python gelieferte CSV-Parser verwendet wird, um diesen Vorgang auszuführen. Dieser Parser verfügt höchstwahrscheinlich über die gesamte Logik, die Sie benötigen.
Hunter McMillen
1

Leider finde ich keine der vorhandenen Antworten besonders befriedigend.

Hier ist eine einfache und vollständige Python 3-Lösung, die das CSV- Modul verwendet.

import csv

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

print(rows)

Beachten Sie das skipinitialspace=TrueArgument. Dies ist notwendig, da die CSV von OP leider nach jedem Komma Leerzeichen enthält.

Ausgabe:

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

Wenn Sie Ihre Anforderungen ein wenig erweitern und davon ausgehen, dass Sie sich nicht um die Reihenfolge der Zeilen kümmern und sie unter Kategorien gruppieren möchten, kann die folgende Lösung für Sie funktionieren:

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

Auf diese Weise erhalten Sie alle relevanten Zeilen im Wörterbuch unter Schlüssel als Kategorie.

Jan Vlcinsky
quelle
0

Hier ist der einfachste Weg in Python 3.x, eine CSV in ein mehrdimensionales Array und seine nur 4 Codezeilen zu importieren, ohne etwas zu importieren!

#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)
Jason Boucher
quelle
Seien Sie vorsichtig, es ist eine Liste, kein Array! Warum nicht einen Kontextmanager verwenden, um das Dateiobjekt richtig zu behandeln? Beachten Sie, dass diese Lösung zusätzliche Leerzeichen für das zweite Element in jeder Zeile hinterlässt und fehlschlägt, wenn eine der Daten ein Komma enthält.
AMC
-1

Als nächstes folgt ein Code, der das CSV-Modul verwendet, aber den Inhalt von file.csv mithilfe der ersten Zeile, die ein Header der CSV-Tabelle ist, in eine Liste von Dikten extrahiert

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
Alexey Antonenko
quelle
1
Warum nicht einfach benutzen csv.DictReader?
AMC