Питон считать файл в массив

Питон: работа с файлами

На серьезных олимпиадах, а также во многих других ситуациях вам надо читать данные не с клавиатуры, а из файла, и выводить данные в файл, а не на «экран». В таком случае вы должны знать имена этих файлов; в задачах они, как правило, указаны, на этом сайте имена файлов почти всегда — input.txt для входных данных и output.txt для выходных.

Во многих языках программирования ввод/вывод данных через файлы очень похож на ввод/вывод с клавиатуры — те же команды, только немного другие параметры. В питоне, к сожалению, это не так.

Ввод данных

Самый простой способ ввести данные из файла в питоне — это сразу считать их в массив строк. Это делается так:

data = open("input.txt", "r").readlines()

Здесь input.txt — файл, откуда надо считать данные, параметр «r» указывает, что вы собираетесь именно читать (read) данные, а не записывать (write, см. ниже). Команда open , как говорят, «открывает файл на чтение», а команда readlines считывает весь файл в массив строк.

Теперь data — это массив строк, каждый элемент которого — это очередная строка из входного файла. Например, если в файле было написано

то data будет содержать массив [«1 2 3\n», «4 5 6\n», «some text\n»] . (Здесь «\n» — это символ перевода строки, он будет на конце каждой строки массива data , кроме, возможно, последней. Если вы считываете числа, то можете о нем не беспокоиться, а если считываете строки и он вам мешает, то, как правило, от него можно избавиться командой a = a.rstrip(«\n») , где a — строка, у которого вы хотите его убрать.)

Каждый элемент массива data — это как результат отдельной команды input() , которой вы пользовались для чтения с клавиатуры. Поэтому дальше вы пишете программу так же, как писали и раньше, но вместо каждого очередного обращения к input() вы обращаетесь к очередному элементу массива data . В простых случаях все просто, в более сложных вам надо аккуратно подсчитывать, к какому именно элементу массива вам надо обратиться.

Пример. Пусть во входном файле два числа по одному на строке. Их считываем так (здесь и далее слева — пример чтения с клавиатуры, справа — из файла):

data = open("input.txt", "r").readlines() a = int(data[0]) b = int(data[1])

Если же два числа в одной строке:

data = open("input.txt", "r").readlines() a, b = map(int, data[0].split())

Более сложный пример: сначала число N , а потом N строк по одному числу в каждой:

n = int(input()) for i in range(n): x = int(input()) #. что-то делаем с x
data = open("input.txt", "r").readlines() n = int(data[0]) for i in range(n): x = int(data[i + 1]) #. что-то делаем с x

Обратите внимание на то, что здесь написано i + 1 — потому что в первой (нулевой) строке было n .

Читайте также:  Вырезать все пробелы php

Вывод

Проще всего выводить данные — записав их в одну большую строку и выведя эту строку. Вывод строки в файл делается так:

здесь s — строка, которую нужно вывести. Это должна быть именно строка, а не число и т.д. Используйте функцию str , чтобы превратить что угодно в строку, вручную добавляйте пробелы и переводы строк (перевод строки записывается так: «\n» ).

Пример: пусть надо вывести два числа в одну строку:

open(«output.txt», «w»).write(str(a) + » » + str(b))

Пусть надо вывести два числа на отдельных строках:

open(«output.txt», «w»).write(str(a) + «\n» + str(b))

Пусть надо вывести массив чисел по одному числу на строке:

s = "" for x in a: s = s + str(x) + "\n" open("output.txt", "w").write(s)

или проще, используя строковую магию:

open("output.txt", "w").write("\n".join(a))

Имейте в виду, что такой вызов должен быть только один раз. Если вы хотите вызывать функцию write несколько раз, то надо суметь вызвать функцию open только один раз. Рекомендуемый вариант — такой:

with open("output.txt", "w") as f: f.write("1") f.write("2")

Источник

Считываем числовые данные из файла на Python

В данной статье речь пойдет о простой на первой взгляд задаче — считывании числовых данных из текстовых файлов на Python. В сети можно найти десятки способов решения этой задачи, однако эти алгоритмы оказываются малоэффективными при работе с большим объемом данных. В данной статье будут разобраны самые популярные методики, а также произведено сравнение их скорости работы.

Введение

Когда я только начинал изучать Python, главным помощником в работе для меня, как наверное и для большинства программистов, был Stack Overflow. Я почерпнул оттуда много полезной информации, в том числе и о работе с файлами. Однако даже такая тривиальная задача, как оказалось, имеет несколько различных решений, отличающихся друг от друга простотой реализации и скоростью работы.

Большинство предложенных методов предполагают чтение файла построчно с дальнейшим разбиением на блоки и их преобразованием из строкового типа в числовой, поскольку Python в отличии от C/C++ работает с файлами как с массивом строк. Выполнить последовательное чтение данных в массив без преобразования типов, как это можно сделать в C/C++, стандартными средствами языка невозможно (насколько мне известно), и это существенно увеличивает время работы программы при обработке больших объемов данных.

Способы чтения данных из файла

Как уже было сказано выше, файлы в Python представляют собой массив строк, поэтому все найденные методы можно символически поделить на два типа в зависимости от используемого подхода:

  • построчное считывание с разбиением и преобразованием типов
  • использование библиотек, которые средствами других языков (например, C/C++) считывают файл и передают полученные данные интерпретатору Python

Ниже представлена подборка самых популярных методов чтения числовых данных на Python, отмеченных сообществом Stack Overflow как «best answer».

Способ 1 — построчное считывание с преобразованием

Самый популярный и простой вариант. Заключается в построчном чтении с разбиением полученной строки на блоки, которые затем преобразуются к необходимому типу данных (в данном случае float) и добавляются к заранее созданному списку.

data = [] with open("data.txt") as f: for line in f: data.append([float(x) for x in line.split()])

Способ 2 — преобразование при помощи map

Способ аналогичен предыдущему, за исключением того, что преобразованием данных из строкового формата в числовой занимается функция map.

file = open("data.txt", "r") data = [map(float, line.split("\t")) for line in file]

Способ 3 — с использованием регулярного выражения

Данный способ можно назвать стрельбой из пушки по воробьям, однако у него все же есть свои плюсы: если данные в файле расположены хаотично и отсутствует постоянная структура, то функции split невозможно задать конкретный разделитель и для решения задачи можно использовать регулярное выражение, которое найдет в строке все числа, несмотря на их расположение и наличие разделителей.

import re file = open("data.txt") values = file.read().split("\n") data = [] for key in values: value = re.findall(r"[-+]?\d*\.\d+|\d+", key) if value != []: data.append(value)

Способ 4 — с использованием CSV Reader

Если данные записаны в виде матрицы с постоянными разделителями, то выполнить их чтение можно при помощи модуля CSV Reader, указав в качестве параметра значение разделителя.

import csv with open("data.txt") as f: data = [map(float, row) for row in csv.reader(f, delimiter='\t')]

Способ 5 — Numpy loadtxt

Библиотека Numpy предоставляет широкий набор модулей и функций для обработки числовых данных, в том числе и для чтения массивов из файлов. Одна из реализаций возможна с помощью функции loadtxt, результат работы которой будет записан в numpy.array.

import numpy as np data = np.loadtxt("data.txt", delimiter='\t', dtype=np.float)

Способ 6 — Numpy genfromtxt

Данный способ не сильно отличается от предыдущего, за исключением того, что genfromtxt предоставляет более широкий набор входных параметров: указание различных типов данных для каждого из столбцов, передача ключей для создания ассоциативного массива и так далее.

import numpy as np data = np.genfromtxt("data.txt", delimiter='\t', dtype=np.float)

Способ 7 — Pandas read_csv

Pandas — мощная библиотека для обработки данных на Python. В данном примере рассматривается только чтение данных, но её возможности этим не ограничены. Метод read_csv предоставляет широкий набор входных параметров, а также показывается высокую скорость работы даже при работе с большими объемами данных.

import pandas as pd data = pd.read_csv("data.txt", sep="\t", header=None)

Методы тестирования скорости чтения

Для тестирования скорости чтения числовых данных были сгенерированы 7 тестовых файлов, содержащих 5 столбцов и 10, 100, 1 000, 10 000, 100 000, 1 000 000 и 10 000 000 строк случайных чисел формата float. Размер самого большого файла составил 742 Мб.

Читайте также:  What is my ip address java

Для измерения времени работы программы использовалась функция time. Существует мнение, что измерять с её помощью время работы некорректно. Однако в данном случае меня интересовало работа с большими объемами данных, когда время работы программы составляло несколько десятков секунд. В таком случае отклонение в полсекунды вносило погрешность менее 1%.

Сравнение с компилируемыми языками программирования

Программы, созданные на компилируемых языках программирования, работают быстрее, чем их аналоги, написанные на интерпретируемых языках. Мне было интересно сравнить скорость чтения каждого метода с Fortran и C++ — самыми популярными языками в научном программировании, с которыми мне также приходится иметь дело в силу специфики моей работы.

Fortran

Несмотря на то, что Fortran считается устаревшим языком, он все еще очень популярен в научном программировании благодаря простоте написания кода, скорости обмена данных и обширном количестве библиотек, созданных за последние полвека.

Например, считать числовую матрицу из файла можно всего за 3 строчки кода при условии корректности входных данных.

real, dimension (5, 1000) :: data open (1, file='data.txt') read(1, *) data

C++

Дискуссии о том, что лучше: Fortran или C++ ведутся уже давно, даже среди авторов EasyCoding этот спор возникал несколько раз, поэтому мне было еще интересней протестировать чтение матриц на данном языке.

ifstream file(«data.txt»); int count = 100000; float** data = new float*[count]; for(int i = 0; i

Результаты тестирования

В ходе эксперимента были протестированы 7 программ на языке Python и по одной на Fortran и C++, код которых представлен выше. Запуск программ осуществлялся на компьютере с Intel Core i5 2.7 GHz и 8 Гб оперативной памяти.

Для запуска программ использовались следующие интерпретаторы и компиляторы:

Для каждой программы проводилась серия испытаний и измерялось время работы, после чего записывался результат в виде среднего арифметического полученных данных. В таблице ниже жирным в каждой строке выделено наименьшее время работы в зависимости от способа чтения и размера входного файла.

Читайте также:  Javascript найти номер элемента
Число строк Способ
1 2 3 4 5 6 7 Fortran C++
10 0.048 0.048 0.045 0.044 0.173 0.216 0.479 0.005 0.005
100 0.053 0.052 0.05 0.048 0.185 0.223 0.511 0.007 0.006
1 000 0.056 0.053 0.053 0.052 0.187 0.233 0.6 0.01 0.01
10 000 0.085 0.076 0.096 0.083 0.305 0.292 0.636 0.032 0.041
100 000 0.414 0.403 0.561 0.482 1.537 0.874 0.796 0.244 0.363
1 000 000 3.835 4.502 6.086 5.276 13.607 6.754 1.763 2.584 3.662
10 000 000 47.931 156.944 137.398 144.75 162.724 85.642 13.632 25.652 36.622

Итог

В ходе данного исследования были протестированы 7 самых популярных варианта чтения числовых матриц на языке Python, предложенными пользователями сайта Stack Overflow и отмеченными сообществом как «верный ответ». Как видно из таблицы с результатами, скорость работы программ не сильно отличается при использовании способов 1-4 на небольших объемах данных. Это связано с тем, что интерпретатор не тратит время на инициализацию сторонней библиотеки, как в методах 5-7.

Однако при увеличении объема входных данных лучше всех себя показал метод 7 с использованием библиотеки Pandas, который даже обогнал по скорости чтения данных языки C++ и Fortran.

Также из результатов теста можно видеть, что программа на Fortran справилась с чтением данных быстрей аналога на C++, что еще раз доказывает его превосходство над самым популярным языком программирования в мире.

10 commentaries to post

Наконец, нашел, что искал. Способ 6 — Numpy genfromtxt, который предоставляет более широкий набор входных параметров: указание различных типов данных для каждого из столбцов, передача ключей для создания ассоциативного массива и так далее.
Спасибо. Сэкономили время на поиск единственного, что нужно для моих вычислений по таблице «тексты-слова»…

FILE* f = fopen(«data.txt», «rb») int count = 10000; float** data = new float*[count]; for(int i = 0; i < count; ++i)

Причем не особо кошерная реализация. Но соответствует предоставленному коду.
Кошерная реализация это:

fread(data, sizeof(float) * 5 * count, f);

Источник

Оцените статью