Python importuje csv do listy


193

Mam plik CSV z około 2000 rekordów.

Każdy rekord ma ciąg i kategorię:

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

Muszę przeczytać ten plik na liście, która wygląda następująco:

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

Jak mogę zaimportować ten plik CSV do listy, której potrzebuję, używając Pythona?


2
Następnie użyj csvmodułu: docs.python.org/2/library/csv.html
furas

4
Jeśli istnieje odpowiedź, która odpowiada Twojemu pytaniu, zaakceptuj ją.
Maciej Gol

Odpowiedzi:


306

Za pomocą modułu csv :

import csv

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

print(data)

Wynik:

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

Jeśli potrzebujesz krotek:

import csv

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

print(data)

Wynik:

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

Odpowiedź na stary Python 2, również za pomocą csvmodułu:

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
Dlaczego używasz „rb” zamiast „r”?
imrek

5
@DrunkenMaster, bpowoduje otwarcie pliku w trybie binarnym, a nie w trybie tekstowym. W niektórych systemach tryb tekstowy oznacza, że \npodczas odczytu lub zapisu zostanie przekonwertowany na nowy wiersz specyficzny dla platformy. Zobacz dokumenty .
Maciej Gol

7
Nie działa to w Pythonie 3.x: „Błąd csv. Iterator powinien zwracać ciągi, a nie bajty (czy otworzyłeś plik w trybie tekstowym?)” Zobacz poniżej odpowiedź, która działa w Pythonie 3.x
Gilbert

2
aby zaoszczędzić kilka sekund czasu na debugowaniu, prawdopodobnie powinieneś dodać notatkę do pierwszego rozwiązania, na przykład „Wersja Python 2.x”
paradite

Jak korzystać z pierwszego rozwiązania, ale tylko z kilkoma kolumnami z pliku csv?
Sigur

54

Zaktualizowano dla Python 3 :

import csv

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

print(your_list)

Wynik:

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

Określanie 'r'jest trybem domyślnym, więc określenie go nie jest konieczne. Dokumenty wspominają również, jeśli plik csv jest plikiem, należy go otworzyć za pomocą newline = ''.
AMC

44

Pandy dobrze radzą sobie z danymi. Oto jeden przykład, jak go używać:

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

Dużą zaletą jest to, że pandy automatycznie zajmują się wierszami nagłówka.

Jeśli nie słyszałeś o Seaborn , polecam go obejrzeć.

Zobacz także: Jak czytać i zapisywać pliki CSV w Pythonie?

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

Zawartość df to:

     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

Treść dykt jest

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

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

Treść listsjest:

[['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]można tuples = list(df.itertuples(index=False))zamiast tego napisać . Należy pamiętać, że dokumenty Pandy odradzają stosowanie .valuesna rzecz .to_numpy(). Trzeci przykład jest dla mnie mylący. Po pierwsze, ponieważ zmienna ma nazwę tuples, co sugerowałoby, że jest to lista krotek, podczas gdy w rzeczywistości jest to lista list. Po drugie, ponieważ o ile wiem, całe wyrażenie można zastąpić df.to_list(). Nie wiem też, czy drugi przykład jest tutaj naprawdę istotny.
AMC

9

Aktualizacja dla 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)

Wynik:

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

Jeśli plik csv jest obiektem pliku, należy go otworzyć za pomocą newline=''.
moduł csv


Dlaczego warto korzystać list(map())ze zrozumienia listy? Zwróć także uwagę na białe znaki na początku każdego elementu drugiej kolumny.
AMC


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

1
Czy możesz dodać trochę wyjaśnienia do tego postu? Tylko kod jest (czasami) dobry, ale kod i objaśnienie jest (w większości przypadków) lepsze
Barranka

3
Wiem, że komentarz Barranki ma ponad rok, ale dla każdego, kto natknie się na to i nie może tego zrozumieć: dla linii w text.splitlines (): umieszcza każdą linię w zmiennej tymczasowej „linia”. line.split („,”) tworzy listę ciągów znaków, które są rozdzielane przecinkiem. tuple (~) umieszcza tę listę w krotce, a append (~) dodaje ją do wyniku. Po pętli wynikiem jest lista krotek, z których każda krotka jest linią, a każdy element krotki jest elementem w pliku csv.
Louis,

Oprócz tego, co powiedział @Louis, nie ma potrzeby używania .read().splitlines(), możesz iterować bezpośrednio po każdej linii pliku: for line in in_file: res.append(tuple(line.rstrip().split(",")))Pamiętaj też, że użycie .split(',')oznacza, że ​​każdy element drugiej kolumny rozpocznie się od dodatkowych białych znaków.
AMC

Dodatek do kodu, który właśnie udostępniłem powyżej: line.rstrip()-> line.rstrip('\n').
AMC

3

Jak już wspomniano w komentarzach, możesz używać csvbiblioteki w Pythonie. csv oznacza wartości oddzielone przecinkami, które wydają się dokładnie twoim przypadkiem: etykieta i wartość oddzielona przecinkiem.

Będąc kategorią i typem wartości wolałbym używać typu słownika zamiast listy krotek.

W każdym razie w poniższym kodzie pokazuję na dwa sposoby: djest słownikiem i llistą krotek.

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)

Dlaczego nie użyć menedżera kontekstu do obsługi pliku? Dlaczego mieszacie dwie różne konwencje nazewnictwa zmiennych? Czy nie jest (row[0], row[1])słabszy / bardziej podatny na błędy niż zwykłe używanie tuple(row)?
AMC

Dlaczego według ciebie wykonywanie krotki (wiersza) jest mniej podatne na błędy? Do jakiej konwencji nazewnictwa zmiennych masz na myśli? Proszę połączyć oficjalną konwencję nazewnictwa Pythona. O ile mi wiadomo, try -except to dobry sposób na obsługę plików: co rozumiesz przez program obsługi kontekstu?
Francesco Boi

Dlaczego według ciebie robienie krotki (wiersza) jest mniej podatne na błędy? Ponieważ nie wymaga ręcznego zapisywania każdego indeksu. Jeśli popełnisz błąd lub liczba elementów ulegnie zmianie, musisz cofnąć się i zmienić kod. Try-wyjątkiem jest w porządku, menedżery kontekstu są instrukcją with. Możesz znaleźć wiele zasobów na ten temat, takich jak ten .
AMC

Nie rozumiem, jak menedżer kontekstu byłby lepszy niż stary dobry blok try-próba. Z drugiej strony pozytywnym aspektem jest to, że wpisujesz mniej kodu; dla reszty, jeśli liczba elementów (myślę, że masz na myśli liczbę kolumn) zmienia moje, to lepiej, ponieważ wyodrębnia tylko pożądane wartości, podczas gdy inne wyodrębnia cały program Excel. Bez żadnego konkretnego wymogu nie można powiedzieć, co jest lepsze, więc strata czasu na kłótnie, co jest lepsze: w tym przypadku oba są ważne
Francesco Boi

Nie rozumiem, jak menedżer kontekstu byłby lepszy niż stary dobry blok try-próba. Zobacz mój poprzedni komentarz, menedżer kontekstu nie zastąpi try-wyjątkiem.
AMC

2

Wystarczy prosta pętla:

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
Co jeśli niektóre wpisy zawierają przecinki?
Tony Ennis

@TonyEnnis Następnie należy użyć bardziej zaawansowanej pętli przetwarzania. Odpowiedź Macieja powyżej pokazuje, jak używać parsera csv dostarczanego z Pythonem do wykonywania tej operacji. Ten parser najprawdopodobniej ma całą logikę, której potrzebujesz.
Hunter McMillen

1

Niestety żadna z istniejących odpowiedzi nie jest szczególnie satysfakcjonująca.

Oto proste i kompletne rozwiązanie Python 3, wykorzystujące moduł csv .

import csv

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

print(rows)

Zwróć uwagę na skipinitialspace=Trueargument. Jest to konieczne, ponieważ niestety CSV OP zawiera białe znaki po każdym przecinku.

Wynik:

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

0

Rozszerzając nieco swoje wymagania i zakładając, że nie obchodzi Cię kolejność wierszy i chcesz je pogrupować w kategorie, może Ci pomóc następujące rozwiązanie:

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

W ten sposób otrzymujesz wszystkie odpowiednie wiersze dostępne w słowniku pod kluczem będącym kategorią.


0

Oto najprostszy sposób na zaimportowanie pliku CSV do tablicy wielowymiarowej w Pythonie 3.x i tylko 4 wiersze kodu bez importowania niczego!

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

Uważaj, to lista, a nie tablica! Dlaczego nie skorzystać z menedżera kontekstu, aby poprawnie obsługiwać obiekt pliku? Zauważ, że to rozwiązanie pozostawia dodatkowe białe znaki na drugim elemencie w każdym wierszu i że zakończy się niepowodzeniem, jeśli którykolwiek z danych zawiera przecinek.
AMC

-1

Dalej jest fragment kodu, który używa modułu csv, ale wypakowuje zawartość file.csv na listę dykt, używając pierwszego wiersza, który jest nagłówkiem tabeli 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
Dlaczego nie po prostu użyć csv.DictReader?
AMC
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.