Как найти минимальные / максимальные значения из строк и столбцов в Python?

Мне было интересно, как мне найти минимальные и максимальные значения из набора данных, который в основном является текстовым файлом. В нем 50 строк, 50 столбцов.

Я знаю, что могу настроить цикл управления (для конкретного цикла), чтобы он читал каждую строку и столбец и определял минимальные / максимальные значения. Но я не знаю, как это сделать.

Я думаю, что сначала нужно преобразовать строки и столбцы в список, а затем мне нужно использовать функцию split(). Я попытался настроить что-то следующим образом, но, похоже, это не сработало:

for x in range(4,50): # using that range as an example
    x.split()
    max(4,50)
    print x

Впервые в Python. Прошу прощения за мои ошибки.


person kaoscify    schedule 21.10.2011    source источник
comment
Как именно выглядит файл? Вы можете предоставить часть файла?   -  person Griffin    schedule 22.10.2011
comment
Вот сценарий, который я написал, который читает все строки в файле, помещает его в список и просматривает список. Это не та программа, которую вы ищете, но она может быть вам полезна.   -  person Griffin    schedule 22.10.2011
comment
@Griffin: Извините, я должен был упомянуть, что это набор данных ASCII. Вот пример - cl.ly/BBqr   -  person kaoscify    schedule 22.10.2011
comment
Вам нужен минимум и максимум каждой строки, или минимум и максимум всего набора данных, или что? Есть ли что-то особенное в первых нескольких строках / столбцах, которые вы хотите исключить? Есть ли что-то особенное в размере данных? Обычно программисты по возможности игнорируют то, что они знают о размере входных данных, предпочитая писать что-то, что будет обрабатывать любой объем данных (обычно это так же просто или даже проще).   -  person Karl Knechtel    schedule 22.10.2011
comment
@KarlKnechtel Мне нужно определить минимум / максимум всего набора данных.   -  person kaoscify    schedule 22.10.2011


Ответы (4)


Попробуйте что-то вроде этого:

data = []
with open('data.txt') as f:
    for line in f:                   # loop over the rows
        fields = line.split()        # parse the columns
        rowdata = map(float, fields) # convert text to numbers
        data.extend(rowdata)         # accumulate the results
print 'Minimum:', min(data)
print 'Maximum:', max(data)

Обратите внимание, что split () принимает необязательный аргумент, если вы хотите разбить что-то кроме пробелов (например, запятые).

person Raymond Hettinger    schedule 21.10.2011
comment
из книги ‹Введение в алгоритмы›, также известной как CLRS. Если мы должны найти и минимум, и максимум одновременно, можно найти минимум и максимум, используя не более 3 * (n // 2) сравнений вместо 2 * n - 2. должен ли python предоставлять что-то вроде minmax ()? - person sunqiang; 22.10.2011
comment
@sunqiang, довольно круто, что количество сравнений можно уменьшить на 25%. Хотя это не так важно, чтобы поместить его в ядро ​​Python, это интересный алгоритм, поэтому я разместил образец кода по адресу code.activestate.com/recipes/577916-fast-minmax-function - person Raymond Hettinger; 22.10.2011
comment
@Raymond Hettinger, Спасибо, что предоставили рецепт за такое короткое время. еще один классный пример itertools,: P - person sunqiang; 23.10.2011
comment
@RaymondHettinger - Спасибо. Я заметил ваши комментарии внутри кода, но, чтобы я понял это правильно, не могли бы вы уточнить fields = line.split(), если это нормально? Раньше я не использовал функцию map. Я только что прочитал об этом в Python Docs. Это по сути сначала превращение текста в список, а затем его преобразование в числа? - person kaoscify; 23.10.2011
comment
Спасибо за этот фрагмент кода. Он отлично сработал: вырезать / вставить в сценарий, над которым я работаю (с небольшими изменениями в соответствии с моими потребностями)! - person Patrick Williams; 22.01.2016

Если файл содержит обычную (прямоугольную) матрицу и вы знаете, сколько строк информации заголовка он содержит, то вы можете пропустить информацию заголовка и использовать NumPy, чтобы сделать это особенно легко:

import numpy as np

f = open("file.txt")
# skip over header info
X = np.loadtxt(f)
max_per_col = X.max(axis=0)
max_per_row = X.max(axis=1)
person Fred Foo    schedule 21.10.2011

Хммм ... вы уверены, что домашнее задание не соответствует ' не применять здесь? ;) Несмотря на:

Вам нужно не только разделить строки ввода, вам нужно преобразовать текстовые значения в числа. Итак, если вы прочитали строку ввода в in_line, вы бы сделали что-то вроде этого:

...
row = [float(each) for each in in_line.split()]
rows.append(row) # assuming you have a list called rows
...

Когда у вас есть список строк, вам нужно получить столбцы:

...
columns = zip(*rows)

Затем вы можете просто перебирать каждую строку и каждый столбец, вызывая max ():

...
for each in rows:
    print max(each)
for eac in columns:
    print max(each)

Изменить. Вот более полный код, показывающий, как открыть файл, перебрать строки файла, закрыть файл и использовать приведенные выше советы:

in_file = open('thefile.txt', 'r')

rows = []
for in_line in in_file:
    row = [float(each) for each in in_line.split()]
    rows.append(row)

in_file.close() # this'll happen at the end of the script / function / method anyhow

columns = zip(*rows)

for index, row in enumerate(rows):
    print "In row %s, Max = %s, Min = %s" % (index, max(row), min(row))

for index, column in enumerate(columns):
    print "In column %s, Max = %s, Min = %s" % (index, max(column), min(column))

Изменить: Для доброты новой школы не используйте мою старую рискованную обработку файлов. Используйте новую безопасную версию:

rows = []
with open('thefile.txt', 'r') as in_file:
    for in_line in in_file:
        row = ....

Теперь у вас есть много гарантий, что вы случайно не сделаете что-то плохое, например, оставите этот файл открытым, даже если вы выбросите исключение во время его чтения. Кроме того, вы можете полностью пропустить in_file.close(), даже не чувствуя себя виноватым.

person gomad    schedule 21.10.2011
comment
Извините, да, я должен был это отметить. Я новичок в Python, практиковался, но иногда мне просто нужна помощь. Спасибо тебе за это. В этом есть смысл. Я попробую это и опубликую здесь свой последний код. - person kaoscify; 22.10.2011
comment
Единственное, что я бы добавил, - это рассмотреть возможность использования модуля csv, но он работает точно так же. - person Austin Marshall; 22.10.2011
comment
@kolor - это не проблема - мне просто пахло домашней работой! :) Очевидно, чтобы найти минимумы, вам также нужно будет выполнить итерацию через вызов min (). - person gomad; 22.10.2011
comment
@AustinMarshall - Я сделал 2 предположения: 1) значения, разделенные пробелами, и 2) Основное внимание в этом упражнении уделялось манипулированию данными, а не чтению их из файла. Я использую и люблю csv, но не хотел вдаваться в подробности. - person gomad; 22.10.2011
comment
@gomad Прежде чем я смогу использовать _1 _... мне нужно определить in_line, верно? Итак, я использую in_line = f.readlines(), но получаю следующую ошибку: AttributeError: 'list' object has no attribute 'split' - person kaoscify; 26.10.2011

Это сработает для вас?

infile = open('my_file.txt', 'r')
file_lines = file.readlines(infile)

for line in file_lines[6:]:
    items = [int(x) for x in line.split()]
    max_item = max(items)
    min_item = min(items)
person jcfollower    schedule 21.10.2011
comment
Привет, jcfollower, спасибо. Не могли бы вы подробнее рассказать о items = [in (x) for x in line.split ()]? Это в основном пытается найти все целочисленные значения в файле? - person kaoscify; 22.10.2011
comment
[int(x) for x in line.split()] означает список, содержащий результат применения int к каждому x в line.split(). line.split() разбивает текст на пробелы, так что у вас есть список слов. int пытается интерпретировать данный текст как целое число. Итак, это создает целое число из каждого слова в данной строке. Он выйдет из строя, если в этой части файла будет мусор. (Часть [6:] в основном пропускает информацию заголовка.) - person Karl Knechtel; 22.10.2011
comment
@KarlKnechtel Спасибо за объяснение! - person kaoscify; 22.10.2011
comment
@jcfollower, я тестировал это на своем наборе данных (cl.ly/BBqr), но, похоже, он выбирает неправильные значения. Основываясь на моем наборе данных, просто взглянув на него в Notepad ++, максимальное значение должно быть 232, а минимальное - 15. Но программа отображает 171 как максимальное и 22 как минимальное. - person kaoscify; 22.10.2011
comment
Цикл for повторно устанавливает max_item и min_item для каждой строки. Предполагалось, что вы будете выполнять больше работы в цикле for с этими значениями в каждой строке. Чтобы получить максимум и минимум всего набора данных, вам нужно будет передать их все одновременно в max и min, создав items, содержащий весь набор данных. Вы должны уметь придумать, как это сделать. Подсказка: попробуйте использовать .readline явно, чтобы пропустить заголовок, а затем используйте .read, чтобы прочитать остальную часть файла в одну строку. Уловка line.split() будет обрабатывать символы новой строки так же, как пробелы. - person Karl Knechtel; 22.10.2011
comment
@KarlKnechtel Хм. Ok. Спасибо. Я попробую. Я вроде как понимаю. Но строка for line in file_lines[6:]: все равно пропускает информацию заголовка, верно? И он читает все остальное содержимое, кроме заголовка. - person kaoscify; 22.10.2011
comment
for line in file_lines[6:] выполняет итерацию по уже прочитанным строкам, за исключением пропуска первых 6. file.readlines читает весь файл и разбивает его на строки. file_lines[6:] - это данные, которые вам нужны, но они разделены одним способом, а вам нужно - другим. Я предложил сделать это правильно с первого раза. Другой способ - сначала соединить строки, а затем снова разбить их на слова. - person Karl Knechtel; 22.10.2011