Python імпортує CSV у список


193

У мене файл CSV з приблизно 2000 записами.

Кожен запис містить рядок і категорію до нього:

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

Мені потрібно прочитати цей файл у списку, який виглядає приблизно так:

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

Як можна імпортувати цей CSV до списку, який мені потрібен за допомогою Python?


2
Потім використовуйте csvмодуль: docs.python.org/2/library/csv.html
furas

4
Якщо є відповідь, яка відповідає вашому питанню, прийміть її.
Maciej Gol

Відповіді:


306

Використання модуля csv :

import csv

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

print(data)

Вихід:

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

Якщо вам потрібні кортежі:

import csv

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

print(data)

Вихід:

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

Старий відповідь Python 2, також використовуючи csvмодуль:

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
Чому ви використовуєте 'rb' замість 'r'?
імрек

5
@DrunkenMaster, bфайл відкриває у двійковому режимі на відміну від текстового режиму. У деяких системах текстовий режим означає, що \nпід час читання або запису буде перетворений новий конкретний платформа. Див. Документи .
Мацей Гол

7
Це не працює в Python 3.x: "csv.Error: ітератор повинен повертати рядки, а не байти (ви відкрили файл у текстовому режимі?"). Див. Нижче відповідь, що працює в Python 3.x
Гілберт

2
щоб заощадити кілька секунд налагодження, вам, мабуть, слід додати примітку до першого рішення, як-от "версія Python 2.x"
парадит

Як використовувати своє перше рішення, але лише деякі стовпці з файлу csv?
Сигур

54

Оновлено для Python 3 :

import csv

with open('file.csv', newline='') 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']]

Зазначення 'r'- це режим за замовчуванням, тому його вказівка ​​зайва. Документи також згадують, якщо csvfile є файловим об'єктом, його слід відкрити з новим рядком = ''.
AMC

44

Панди досить добре справляються з даними. Ось один із прикладів його використання:

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

Одна велика перевага полягає в тому, що панди автоматично обробляють заголовки.

Якщо ви ще не чули про Seaborn , рекомендую поглянути на нього.

Дивіться також: Як я можу читати та записувати файли CSV за допомогою Python?

Панди №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')

Вміст 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

Зміст диктів є

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

Панди №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')]

Зміст 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]можна записати tuples = list(df.itertuples(index=False))замість цього. Зауважте, що документи Pandas перешкоджають використанню .valuesна користь .to_numpy(). Третій приклад мене бентежить. По-перше, тому, що названа змінна tuples, що означає, що це список кортежів, тоді як насправді це список. По-друге, тому що, наскільки я можу сказати, цілий вираз можна замінити на df.to_list(). Я також не знаю, чи є другий приклад справді актуальним.
AMC

9

Оновлення для 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)

Вихід:

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

Якщо csvfile є файловим об'єктом, його слід відкрити newline=''.
модуль csv


Навіщо використовувати list(map())над розумінням списку? Також помітьте пробіл у на початку кожного елемента другого стовпця.
AMC

5

Якщо ви впевнені, що у вашому введенні немає коми, крім того, щоб розділити категорію, ви можете прочитати файл за рядком і розділити далі ,, а потім натиснути результат наList

При цьому, схоже, ви переглядаєте файл CSV, тож ви можете розглянути можливість використання модулів для нього


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

1
Чи можете ви додати трохи пояснень до цієї публікації? Код лише (іноді) хороший, але код і пояснення (у більшості разів) кращі
Barranka

3
Я знаю, що коментар Барранки вже понад рік, але для тих, хто натрапляє на це і не може цього зрозуміти: для рядка в text.splitlines (): ставить кожен окремий рядок у змінну temp "рядок". line.split (",") створює список рядків, розділених на коми. tuple (~) ставить цей список у кортеж, а додаток (~) додає його до результату. Після циклу результат - це список кортежів, з кожним кортежем рядка, а кожен елемент кортежу - елемент у файлі csv.
Луї

На додаток до того, що сказав @Louis, немає необхідності використовувати .read().splitlines(), ви можете переглядати кожен рядок файлу безпосередньо: for line in in_file: res.append(tuple(line.rstrip().split(",")))Також зауважте, що використання .split(',')засобів означає, що кожен елемент другого стовпця починатиметься з додаткового пробілу.
AMC

Додаток до коду, яким я лише поділився вище: line.rstrip()-> line.rstrip('\n').
AMC

3

Як вже сказано в коментарях, ви можете використовувати csvбібліотеку в python. csv означає значення, розділені комами, що здається саме вашим випадком: мітка та значення, розділені комою.

Будучи категорією та типом значення, я б скоріше використовував тип словника, а не список кортежів.

У будь-якому випадку в коді нижче я показую обидва способи: dце словник та lсписок кортежів.

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)

Чому б не використовувати менеджер контексту для обробки файлу? Чому ви змішуєте дві різні умови іменування змінних? Чи не (row[0], row[1])слабкіше / більш схильне до помилок, ніж просто використання tuple(row)?
AMC

Чому ви думаєте, що робити кортеж (рядок) менш схильний до помилок? Зв’яжіть офіційну конвенцію про іменування пітона. Наскільки я знаю, спробуйте -except - це хороший спосіб обробки файлів: що ви розумієте під контекстним обробником?
Франческо Бой

Чому ви думаєте, що робити кортеж (рядок) менш схильний до помилок? Тому що для цього не потрібно писати кожен індекс вручну. Якщо ви допустили помилку, або кількість елементів змінюється, вам доведеться повернутися назад і змінити свій код. Спроба, окрім цього, чудова, менеджери контексту - це заява. Ви можете знайти безліч ресурсів на цю тему, наприклад, цей .
AMC

Я не бачу, наскільки менеджер контексту був би кращим за добрий спробу, крім блоку. Для іншого позитивним аспектом є те, що ви вводите менше коду; для решти, якщо кількість елементів (я думаю, маю на увазі кількість стовпців) змінює мою, тому що вона витягує лише потрібні значення, а інша - витягує всі excel. Без будь-якої конкретної вимоги ви не можете сказати, що краще, тому марно витрачати час, сперечаючись, що краще: у цьому випадку обидва дійсні
Франческо Бой

Я не бачу, наскільки менеджер контексту був би кращим за добрий спробу, крім блоку. Будь ласка, дивіться мій попередній коментар, менеджер контексту не замінить пробний виняток.
AMC

2

Досить простого циклу:

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
Що робити, якщо в деяких записах є коми?
Тоні Енніс

@TonyEnnis Тоді вам потрібно буде використовувати більш вдосконалений цикл обробки. Відповідь Мацея вище показує, як використовувати аналізатор csv, який постачається з Python, для виконання цієї операції. Цей аналізатор, швидше за все, має всю необхідну вам логіку.
Мисливець Макміллен

1

На жаль, я не вважаю жодної із існуючих відповідей особливо задовольняючої.

Ось просте і повне рішення Python 3, використовуючи модуль csv .

import csv

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

print(rows)

Зауважте skipinitialspace=Trueаргумент. Це необхідно, оскільки, на жаль, CSV ОП містить пробіл після кожної коми.

Вихід:

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

0

Трохи розширивши свої вимоги та припустивши, що ви не піклуєтесь про порядок рядків і хочете їх згрупувати за категоріями, наступне рішення може вам підійти:

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

Таким чином ви отримуєте всі відповідні рядки, доступні в словнику під клавішею категорії.


0

Ось найпростіший спосіб в Python 3.x імпортувати CSV в багатовимірний масив, і лише його 4 рядки коду, не імпортуючи нічого!

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

Будьте уважні, це список, а не масив! Чому б не використовувати диспетчер контексту для належного керування файловим об’єктом? Зауважте, що це рішення залишає зайвий пробіл на другому елементі у кожному рядку, і що воно не вдасться, якщо будь-який із даних містить кому.
AMC

-1

Далі - фрагмент коду, який використовує модуль csv, але витягує вміст file.csv до списку диктів, використовуючи перший рядок, який є заголовком таблиці 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
Чому б просто не використовувати csv.DictReader?
AMC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.