Считать строку чисел питон

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

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

Введение

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

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

Читайте также:  Удалить тег xml php

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

Как уже было сказано выше, файлы в 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 Мб.

Для измерения времени работы программы использовалась функция 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 Гб оперативной памяти.

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

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

Число строк Способ
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);

Источник

Пользовательский ввод чисел в строку

Функция input() возвращает все в виде строки, поэтому нужно выполнить явную конвертацию, чтобы получить целое число. Для этого пригодится функция int() .

 
# вывод суммы двух чисел, введенных пользователем

num_1 = int(input("Введите первое число: "))
num_2 = int(input("Введите второе число: "))

print("Тип num_1:", type(num_1))
print("Тип num_2:", type(num_2))

result = num_1 + num_2
print("Сумма введенных чисел:", result)

int(string) конвертирует переданную строку в целое число.

Ввода числа float

По аналогии можно использовать функцию float() .

 
float_1 = float(input("Введите число: "))
print("Тип float_1:", type(float_1))

result = float_1 ** 2
print("Число в квадрате:", result)
Введите число: 1.8 Тип float_1: Число в квадрате: 3.24

Ввод чисел в строку через пробел

Но что произойдет, если вы не знаете количество элементов ввода?

Предположим, что от пользователя нужно получить список чисел и вернуть их сумму. При этом вы не знаете количество элементов в этом списке. Как же запросить ввод для него?

Для этого можно использовать split и функции map . Метод split() делит введенную строку на список подстрок. После этого map() выполняет функцию int() для каждого элемента списка.

 
entered_list = input("Введите список чисел, разделенных пробелом: ").split()
print("Введенный список:", entered_list)

num_list = list(map(int, entered_list))
print("Список чисел: ", num_list)
print("Сумма списка:", sum(num_list))
Введите список чисел, разделенных пробелом: 1 34 4 6548 Введенный список: ['1', '34', '4', '6548'] Список чисел: [1, 34, 4, 6548] Сумма списка: 6587
  • input() возвращает список, содержащий числа, разделенные запятыми.
  • split() возвращает список строк, разделенных пробелами.
  • map() выполняет операцию int() для всех элементов списка и возвращает объект map .
  • list() конвертирует объект map снова в список.

Есть альтернативный способ получить список:

 
entered_list = input("Введите список чисел, разделенных пробелом: ").split()

num_list = [int(i) for i in entered_list]
print("Список чисел: ", num_list)

Обработка ошибок при пользовательском вводе

Часто при конвертации типов возникает исключение ValueError .

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

Например, пользователь вводит случайную строку в качестве возраста.

 
num = int(input("Введите возраст: "))

Функция int() ожидает целочисленное значение, обернутое в строку. Любое другое значение приводит к ошибке. Вот что будет, если, попробовать ввести «Двадцать»:

Введите возраст: Двадцать --------------------------------------------------------- ValueError Traceback (most recent call last) in ----> 1 num_1 = int(input('Введите возраст: ')) ValueError: invalid literal for int() with base 10: 'Двадцать'

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

 
try:
num = int(input("Введите число: "))
print("Все верно. Число:", num)
except ValueError:
print("Это не число.")

Посмотрим, как ввод «Двадцать» сработает теперь:

Введите число: Двадцать Это не число.

В этом примере если пользователь вводит нечисловое значение, то возникает исключение. Однако оно перехватывается инструкцией except , которая в ответ выводит: «Это не число». Благодаря использованию конструкции try-except программа не прекратит работать при некорректном вводе.

Обучение с трудоустройством

Я создал этот блог в 2018 году, чтобы распространять полезные учебные материалы, документации и уроки на русском. На сайте опубликовано множество статей по основам python и библиотекам, уроков для начинающих и примеров написания программ.

Python Q CEO Pythonru admin@pythonru.com https://secure.gravatar.com/avatar/b16f253879f7349f64830c64d1da4415?s=96&d=mm&r=g CEO Pythonru Python Александр Редактор https://t.me/cashncarryhttps://pythonru.com/https://yandex.ru/q/profile/cashnc/ PythonRu.com admin@pythonru.com Alex Zabrodin 2018-10-26 Online Python, Programming, HTML, CSS, JavaScript

Источник

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