Модуль array. Массивы в python

Модуль array определяет массивы в python. Массивы очень похожи на списки, но с ограничением на тип данных и размер каждого элемента.
Размер и тип элемента в массиве определяется при его создании и может принимать следующие значения:
| Код типа | Тип в C | Тип в python | Минимальный размер в байтах |
|---|---|---|---|
| ‘b’ | signed char | int | 1 |
| ‘B’ | unsigned char | int | 1 |
| ‘h’ | signed short | int | 2 |
| ‘H’ | unsigned short | int | 2 |
| ‘i’ | signed int | int | 2 |
| ‘I’ | unsigned int | int | 2 |
| ‘l’ | signed long | int | 4 |
| ‘L’ | unsigned long | int | 4 |
| ‘q’ | signed long long | int | 8 |
| ‘Q’ | unsigned long long | int | 8 |
| ‘f’ | float | float | 4 |
| ‘d’ | double | float | 8 |
Класс array.array(TypeCode [, инициализатор]) — новый массив, элементы которого ограничены TypeCode, и инициализатор, который должен быть списком, объектом, который поддерживает интерфейс буфера, или итерируемый объект.
array.typecodes — строка, содержащая все возможные типы в массиве.
Массивы изменяемы. Массивы поддерживают все списковые методы (индексация, срезы, умножения, итерации), и другие методы.
Методы массивов (array) в python
array.typecode — TypeCode символ, использованный при создании массива.
array.itemsize — размер в байтах одного элемента в массиве.
array.append(х) — добавление элемента в конец массива.
array.buffer_info() — кортеж (ячейка памяти, длина). Полезно для низкоуровневых операций.
array.byteswap() — изменить порядок следования байтов в каждом элементе массива. Полезно при чтении данных из файла, написанного на машине с другим порядком байтов.
array.count(х) — возвращает количество вхождений х в массив.
array.extend(iter) — добавление элементов из объекта в массив.
array.frombytes(b) — делает массив array из массива байт. Количество байт должно быть кратно размеру одного элемента в массиве.
array.fromfile(F, N) — читает N элементов из файла и добавляет их в конец массива. Файл должен быть открыт на бинарное чтение. Если доступно меньше N элементов, генерируется исключение EOFError , но элементы, которые были доступны, добавляются в массив.
array.fromlist(список) — добавление элементов из списка.
array.index(х) — номер первого вхождения x в массив.
array.insert(n, х) — включить новый пункт со значением х в массиве перед номером n. Отрицательные значения рассматриваются относительно конца массива.
array.pop(i) — удаляет i-ый элемент из массива и возвращает его. По умолчанию удаляется последний элемент.
array.remove(х) — удалить первое вхождение х из массива.
array.reverse() — обратный порядок элементов в массиве.
array.tobytes() — преобразование к байтам.
array.tofile(f) — запись массива в открытый файл.
array.tolist() — преобразование массива в список.
Вот и всё, что можно было рассказать про массивы. Они используются редко, когда нужно достичь высокой скорости работы. В остальных случаях массивы можно заменить другими типами данных: списками, кортежами, строками.
Для вставки кода на Python в комментарий заключайте его в теги
Массивы
Элементы списка могут вводиться по одному в строке, в этом случае строку можно считать функцией input(). После этого можно использовать метод строки split, возвращающий список строк, разрезав исходную строку на части по пробелам. Пример:
A = input().split()
Если при запуске этой программы ввести строку 1 2 3, то список A будет равен ['1', '2', '3']. Обратите внимание, что список будет состоять из строк, а не из чисел. Если хочется получить список именно из чисел, то можно затем элементы списка по одному преобразовать в числа:
for i in range(len(A)):
A[i] = int(A[i])
Используя функции языка map и list то же самое можно сделать в одну строку:
A = list(map(int, input().split()))
Объяснений, как работает этот код, пока не будет. Если нужно считать список действительных чисел, то нужно заменить тип int на тип float.
У метода split есть необязательный параметр, который определяет, какая строка будет использоваться в качестве разделителя между элементами списка. Например, метод split('.') вернет список, полученный разрезанием исходной строки по символам '.'.
Используя “обратные” методы можно вывести список при помощи однострочной команды. Для этого используется метод строки join. У этого метода один параметр: список строк. В результате получается строка, полученная соединением элементов списка (которые переданы в качестве параметра) в одну строку, при этом между элементами списка вставляется разделитель, равный той строке, к которой применяется метод. Например программа
A = ['red', 'green', 'blue']
print(' '.join(A))
print(''.join(A))
print('***'.join(A))
выведет строки 'red green blue', redgreenblue и red***green***blue.
Если же список состоит из чисел, то придется использовать еще и функцию map. То есть вывести элементы списка чисел, разделяя их пробелами, можно так:
print(' '.join(map(str, A)))
Массивы
Массив (англ. array) - структура данных, хранящая набор значений. Каждое значение из набора индексируется, т.е. значения имеют номера (индексы).
Простейший массив имеет следующий интерфейс
- создать(A, N) -> массив A длины N - создание массива A размера N .
- записать(A, i, x) - записывает значение x в i -ый элемент массива A .
- считать(A, i) -> элемент массива A с индексом i - взятие элемента по индексу (чтение).
- удалить(A) - удаление массива А .
Обычно индексами массива являются целые положительные числа, причём в непрерывном диапазоне. Например, 0, 1, 2. N-2, N-1 , где N - размер массива. В таком случае массив упорядочен по индексу и можно говорить, что массив также является последовательностью.
Для массива операции чтения и записи выполняются за O(1) , т.е. время этих операций не зависит от количества элементов в массиве.
Массив в Python
Массив в Python
упорядоченная изменяемая последовательность. массив хранит множество элементов, которые образуют последовательность. При этом можно изменять как сами элементы массива, так и сам массив: пополнять массив новыми элементами или удалять их. . объектов произвольных типов элементами массива являются Python-объекты. При этом допускается, чтобы в одном массиве хранились объекты разных типов.
Массивы в Python также называют списками или листами (англ. list). Терминология в других языках программирования, а также в теории алгоритмов может быть другая.
Список Python является гибким в использовании объектом. Как инструмент, программист может использовать списки, например, для создания элементов линейной алгебры: точек, векторов, матриц, тензоров. Или, например, для таблицы с некоторыми данными.
Важно заметить, что , питоновский список, является универсальной структурой данных. В том числе, ей можно пользоваться как массивом (что мы и будем делать)! То есть, у этого объекта есть интерфейс, описанный в предыдущем разделе, причём с теми же асимптотиками, хотя возможности выходят гораздо за пределы простейшего массива.
Создание массива
Литерал массива
Массив можно создать при помощи литералов. Литерал - это код, который используется для создания объекта "вручную" (задания константы). Например, некоторые литералы уже изученных ранее объектов:
- int : 5 , -23
- float : 5. , 5.0 , -10.81 , -1.081e1
- str : 'ABCdef' , "ABCdef"
В случае массива литералом являются квадратные скобки [] , внутри которых через запятую , перечисляются элементы массива:
>>> [] [] >>> [0, 1, 2, 3, 4] [0, 1, 2, 3, 4] >>> ['sapere', 'aude'] ['sapere', 'aude'] >>> ['Gravitational acceleration', 9.80665, 'm s^-2'] ['Gravitational acceleration', 9.80665, 'm s^-2'] >>> type([0, 1, 2, 3, 4])
Создание массива заданной длины, склеивание массивов
Чтобы создать массив наперёд заданной длины, нужно задать инициализируещее значение и длину. Ниже создаётся массив, содержащий 10 нулей.
>>> A = [0] * 10 >>> A [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] >>> type(A)
С похожим синтаксисом мы сталкивались при работе со строками. Массивы в Python можно "склеивать" с помощью знака сложения:
>>> A = [0] * 3 # [0, 0, 0] >>> B = [1] * 3 # [1, 1, 1] >>> C = [2] * 3 # [2, 2, 2] >>> D = A + B + C >>> D [0, 0, 0, 1, 1, 1, 2, 2, 2]
На самом деле, умножение массива на целое число M это создание нового массива путём M "склеиваний" исходного массива с самим собой:
>>> [0, 1] * 3 [0, 1, 0, 1, 0, 1] >>> [0, 1] + [0, 1] + [0, 1] [0, 1, 0, 1, 0, 1]
Элементы массива: доступ и изменение
Выше мы убедились, что массив это множество объектов различных типов, теперь убедимся, что это упорядоченная последовательность изменяемых объектов.
Доступ по индексу
Для доступа к элементам массива используется операция взятия элемента по индексу. Для этого рядом с литералом или переменной массива необходимо подписать индекс элемента в квадратных скобках:
>>> ['Gravitational acceleration', 9.80665, 'm s^-2'][0] 'Gravitational acceleration' >>> ['Gravitational acceleration', 9.80665, 'm s^-2'][1] 9.80665 >>> ['Gravitational acceleration', 9.80665, 'm s^-2'][2] 'm s^-2' >>> l = [10, 20, 30] >>> l[0] 10 >>> l[1] 20 >>> l[2] 30
Нумерация элементов массива начинается с нуля.
При запросе элемента по несуществующему индексу, Python вызовет ошибку IndexError:
>>> l [10, 20, 30] >>> l[3] Traceback (most recent call last): File "", line 1, in IndexError: list index out of range
Поэтому всегда нужно быть уверенным, что индексация не выходит за пределы длины массива. Получить её можно с помощью функции len() :
>>> l [10, 20, 30] >>> len(l) 3 >>> l[len(l) - 1] 30
Последняя конструкция встречается нередко, поэтому в Python существует возможность взять элемент по отрицательному индексу:
>>> l [10, 20, 30] >>> l[-1] 30 >>> l[-2] 20 >>> l[-3] 10 >>> l[-4] Traceback (most recent call last): File "", line 1, in IndexError: list index out of range
Таким образом для индекса n ≥ 0, l[-n] эвивалентно l[len(l) - n] .
Изменение элементов
Изменение элементов осуществляется с помощью присваивания:
>>> l = [10, 20, 30] >>> l [10, 20, 30] >>> l[0] = 0 >>> l [0, 20, 30] >>> l[2] = 55 >>> l [0, 20, 55]
Доступ в цикле while
>>> l [0, 20, 55] >>> i = 0 >>> while i len(l): . print(i, l[i]) . i += 1 . 0 0 1 20 2 55 >>>
Доступ в цикле for
Наиболее универсальный способ это использование генератора range:
>>> l [0, 20, 55] >>> for i in range(len(l)): . print(i, l[i]) . 0 0 1 20 2 55
Печать массива
Чтобы распечатать элементы массива в столбец, воспользуйтесь циклом for , как в разделе выше.
Если нужно распечатать массив в строку, то воспользуйтесь функцией print :
>>> A = [0, 1, 2, 3] >>> print(*A) 0 1 2 3
Здесь знак * это операция развёртывания коллекции по аргументам функции. Функция print принимает на вход сколько угодно аргументов и действие выше эквиваленто следующему:
>>> print(A[0], A[1], A[2], A[3]) 0 1 2 3
Ремарка о строках
На самом деле, мы уже ранее сталкивались с массивами в предудыщих лабораторных, когда использовали строковый метод str.split :
>>> s = "ab cd ef1 2 301" >>> s.split() ['ab', 'cd', 'ef1', '2', '301']
Т.е. str.split , по умолчанию, разбивает строку по символам пустого пространства (пробел, табуляция) и создаёт массив из получившихся "слов".
Загляните в help(str.split) , чтобы узнать, как изменить такое поведение, и разбивать строку, например, по запятым, что является стандартом для представления таблиц в файлах csv (comma separated values).
Методом, являющимся обратным к операции str.split является str.join . Он "собирает" строку из массива строк:
>>> s 'ab cd ef1 2 301' >>> l = s.split() >>> l ['ab', 'cd', 'ef1', '2', '301'] >>> l[-1] = '430' >>> l ['ab', 'cd', 'ef1', '2', '430'] >>> ','.join(l) 'ab,cd,ef1,2,430' >>> ' -- '.join(l) 'ab -- cd -- ef1 -- 2 -- 430'
Работа с двумерными массивами
Как вам рассказали, в массиве мы можем хранить различные данные. В том числе в ячейке массива можем хранить другой массив. Давайте предположим, что в каждой ячейке массива размера N у нас будет храниться другой массив размера M . Таким образом мы можем построить таблицу или матрицу размера N x M .
Создание двумерного массива (матрицы) размера N x M в питоне:
a = [] for _ in range(n): a.append([0] * m)
a = [[0] * m for _ in range(n)]
Обращение к элементами двумерного массива:
a[i][j] = 5
Фильтрация значений и вырезание — Python: Numpy-массивы
При работе с данными часто возникает необходимость найти элементы по определенному условию. С точки зрения поиска ошибок в данных критерии поиска могут быть разными, например:
- Отрицательные значения в графе «Количество продаж»
- Буквы вместо цифр в графе «Номер телефона»
- Нереалистично большие числа в графе «Сумма сделки»
В стандартном Python искать и фильтровать значения можно с помощью функции filter() . В Numpy есть схожая функциональность, которую мы рассмотрим в этом уроке. Вы узнаете, как получить элементы по заданному условию при работе с массивами numpy.ndarray .
Как создать булеву маску
Для фильтрации значений массива numpy.ndarray по определенному условию используют булевы маски — массивы значений True и False . Каждый элемент проходит фильтрацию через булеву маску и распределяется в зависимости от значения маски:
- Если на той же позиции в маске стоит значение True , элемент добавляется в итоговый массив
- Если на позиции стоит значение False , то элемент не будет включен в итоговый массив
Существует три способа работы с булевой маской:
- Создать массив значений True и False вручную
- Использовать операторы сравнения над элементами исходного массива
- Применить логическое отрицание к текущей маске — поменять True на False и наоборот
Так все три способа выглядят в коде:
import numpy as np # Исходный массив base_array = np.array([0, 1, 2, 3, 4, 5, 6, 7,]) print(base_array) # => [0 1 2 3 4 5 6 7] # Ручное создание маски handmade_mask = [True, True, True, False, False, False, False, False,] print(handmade_mask) # => [True, True, True, False, False, False, False, False] # Создание маски по условию compare_mask = base_array 3 print(compare_mask) # => [ True True True False False False False False] # Создание маски по логическому отрицанию условия opposite_compare_mask = ~(base_array >= 3) print(opposite_compare_mask) # => [ True True True False False False False False]
Первый способ на практике встречается редко, потому что на ручное создание маски уходит слишком много времени, особенно при большом размере массива:
Как применять маску
Чтобы применить булеву маску к исходному массиву, достаточно подставить ее в качестве индекса:
print(base_array[handmade_mask]) # => [0 1 2] print(base_array[compare_mask]) # => [0 1 2] print(base_array[opposite_compare_mask]) # => [0 1 2]
Как мы говорили выше, в Python реализована функция filter() , которая применяется для итеративной фильтрации значений списка по условию:
# Фильтрация значений с использованием filter filtered_list = list( filter( lambda x: x 3, [0, 1, 2, 3, 4, 5, 6, 7,] ) ) print(filtered_list) # => [0 1 2]
Для итеративной фильтрации элементов массива numpy.ndarray используется другой способ — метод numpy.fromiter() :
# Итеративное создание нового массива с использованием fromiter, тип массива задается аргументом dtype filtered_array = np.fromiter( (base_array_element for base_array_element in base_array if base_array_element 3), dtype = base_array.dtype ) print(filtered_array) # => [0 1 2]
На практике часто требуется не только убирать значения из исходного массива, но и заменять их. Для этого используется метод numpy.where() :
# Заменяем отфильтрованные элементы на 0 print(np.where(base_array 3, base_array, 0)) # => [0 1 2 0 0 0 0 0]
Если для фильтрации мы используем составное условие, лучше инициализировать маску отдельно. Это упрощает поддержку и делает код более читабельным:
# Заменяем отфильтрованные элементы на 0 с использованием маски compare_masks = (base_array > 5) | (base_array 3) print(np.where(compare_masks, base_array, 0)) # => [0 1 2 0 0 0 6 7]
В реальных данных регулярно возникают пропущенные значения. Это может происходить из-за человеческого фактора, сбоя в работе сервисов или ошибки при записи в базу данных. Для таких случаев в Numpy существует отдельный тип данных numpy.nan (not a number):
# Массив с пропущенными значениями raw_array = np.array([0, 1, None, 3, 4, None, 6, 7,], dtype=np.float64) print(raw_array) # => [ 0. 1. nan 3. 4. nan 6. 7.]
Для корректной работы программ необходимо обнаруживать пропуски, чистить данные от них или заменять на значение по умолчанию.
Рассмотрим на примере. Сначала нужно обнаружить пропуски:
# Маска для поиска пропусков nan_mask = np.isnan(raw_array) print(nan_mask) # => [False False True False False True False False]
Затем чистим данные от пропусков:
# Маска для фильтрации пропущенных значений not_nan_mask = ~nan_mask print(raw_array[not_nan_mask]) # => [0. 1. 3. 4. 6. 7.]
Теперь заменяем пропуски на некоторое значение:
# Заменяем пропуски на 0 print(np.where(nan_mask, 0, raw_array)) # => [0. 1. 0. 3. 4. 0. 6. 7.]
Как применять маску с двумерными массивами
Выше мы рассмотрели фильтрацию значений на примере одномерного массива. Те же принципы применимы и в работе с двумерными массивами. Рассмотрим пример задачи — подготовим сырые данные продаж магазина ноутбуков по следующим шагам:
- Сначала обнаружим выбросы двух типов — значения выше 200 и отрицательные значения. Число 200 выбрано потому, что именно столько ноутбуков хранится на складе. Менеджер магазина знает, что в день не бывает более 200 продаж
- Затем заменим выбросы и пропуски на среднее значение продаж
Мы проводим эти операции, чтобы подготовить сырые данные к более глубокому анализу с применением методов статистики и машинного обучения:
# Создаем список списков продаж четырех магазинов orders_values = [ [7, 1, -7, None], [1000, 2, 4, None], [3, None, 503, 3], [8, 12, 8, 7], [15, 11, None, 9], [None, 18, 17, -21], [252, 16, 25, 17] ] # Конвертируем в Numpy-массив orders = np.array(orders_values, dtype=np.float64) print(orders) # => [[ 7. 1. -7. nan] # [1000. 2. 4. nan] # [ 3. nan 503. 3.] # [ 8. 12. 8. 7.] # [ 15. 11. nan 9.] # [ nan 18. 17. -21.] # [ 252. 16. 25. 17.]]
Чтобы отфильтровать значения, нужно создать маски:
# Маска для отрицательных значений negative_values = orders 0 print(orders[negative_values]) # => [ -7. -21.] # Маска для больших значений big_values = orders > 200 print(orders[big_values]) # => [1000. 503. 252.] # Маска для пропущенных значений и подсчета их количества nan_values = np.isnan(orders) print(sum(sum(nan_values))) # => 5
Чтобы найти средние значения, нужно оставить только стандартные значения продаж. Сделать это можно маской, объединяющей логические отрицания сформированных масок:
# Маска стандартных значений normal_mask = ~negative_values & ~big_values & ~nan_values # Стандартные значения заказов normal_values = orders[normal_mask] # Среднее значение для стандартных заказов normal_mean = normal_values.mean() normal_mean = int(normal_mean) print(normal_mean) # => 10
Далее остается только заменить нестандартные значения на величину среднего:
# Массив, в котором нестандартные значения заменены на среднее prepared_orders = np.where(normal_mask, orders, normal_mean) print(prepared_orders) # => [[ 7. 1. 10. 10.] # [10. 2. 4. 10.] # [ 3. 10. 10. 3.] # [ 8. 12. 8. 7.] # [15. 11. 10. 9.] # [10. 18. 17. 10.] # [10. 16. 25. 17.]]
Выводы
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях: