Создание массивов NumPy
NumPy предоставляет десятки способов создания массивов ndarray — основной структуры данных библиотеки. Правильный выбор функции создания экономит память, ускоряет работу и делает код выразительным.
В этой статье мы рассмотрим базовые функции: преобразование из Python-списков, создание заполненных нулями/единицами массивов, генерация числовых последовательностей и работу с типами данных dtype.
Зачем нужно
Когда вы пишете программу для обработки данных с Arduino (например, измерений температуры за час), удобнее работать не с обычным Python-списком, а с массивом NumPy. Причины:
Скорость. Операции над
ndarrayнаписаны на C и выполняются в десятки раз быстрее циклаfor.Память. Массив фиксированного типа хранится компактно, без накладных расходов на объекты Python.
Удобство. Векторные операции (
a + b,a * 2) применяются ко всем элементам сразу.
Пример 1. Создание из Python-списка
Самый простой способ — преобразовать список или вложенный список через np.array.
import numpy as np
# Температура с датчика DS18B20 за 5 секунд
temps = np.array([23.1, 23.4, 23.5, 23.3, 23.6])
print(temps)
print(temps.dtype, temps.shape)
[23.1 23.4 23.5 23.3 23.6]
float64 (5,)
Атрибут dtype показывает тип элементов, shape — форму массива (одномерный из 5 элементов).
Пример 2. Двумерный массив (матрица)
Передаём вложенный список — получаем матрицу. Удобно для табличных данных.
import numpy as np
# 3 датчика, 4 измерения
data = np.array([
[20.1, 20.2, 20.0, 20.3],
[21.5, 21.4, 21.6, 21.5],
[19.8, 19.9, 19.7, 19.8],
])
print(data.shape)
print(data)
(3, 4)
[[20.1 20.2 20. 20.3]
[21.5 21.4 21.6 21.5]
[19.8 19.9 19.7 19.8]]
Пример 3. np.zeros и np.ones
Часто нужно создать массив-«заготовку», заполненный нулями или единицами, чтобы потом записать в него данные.
import numpy as np
buffer = np.zeros(8) # буфер на 8 значений
mask = np.ones((2, 3), dtype=int) # матрица 2x3 из единиц, тип int
print(buffer)
print(mask)
[0. 0. 0. 0. 0. 0. 0. 0.]
[[1 1 1]
[1 1 1]]
По умолчанию np.zeros создаёт массив типа float64. Если нужны целые числа — указывайте dtype=int.
Пример 4. np.arange — диапазон с шагом
Аналог встроенной функции range, но возвращает массив. Полезен для генерации индексов и временных шкал.
import numpy as np
indices = np.arange(0, 10, 2) # от 0 до 10 с шагом 2
t_ms = np.arange(0, 1000, 100) # моменты времени в мс
print(indices)
print(t_ms)
[0 2 4 6 8]
[ 0 100 200 300 400 500 600 700 800 900]
Шаг может быть дробным, в отличие от range: np.arange(0, 1, 0.25) даёт [0. 0.25 0.5 0.75].
Пример 5. np.linspace — равномерное разбиение
В отличие от arange, linspace принимает не шаг, а количество точек. Удобно для построения графиков и калибровочных кривых.
import numpy as np
# 5 уровней ШИМ от 0 до 255
pwm = np.linspace(0, 255, 5)
print(pwm)
[ 0. 63.75 127.5 191.25 255. ]
По умолчанию конечная точка включена. Чтобы исключить — передайте endpoint=False.
Пример 6. np.full — заполнение константой
Создаёт массив заданной формы, заполненный одним значением.
import numpy as np
default_pwm = np.full((4,), 128, dtype=np.uint8)
print(default_pwm)
print(default_pwm.dtype)
[128 128 128 128]
uint8
Тип uint8 (0–255) идеально подходит для ШИМ-значений Arduino — экономит память по сравнению с int64.
Пример 7. np.empty — без инициализации
Самый быстрый способ создать массив, но содержимое — «мусор» из памяти.
import numpy as np
buf = np.empty(5)
print(buf) # значения непредсказуемые
[6.9e-310 6.9e-310 0.0e+000 0.0e+000 0.0e+000]
Используйте, только когда сразу же перезаписываете все элементы — иначе получите случайные числа.
Пример 8. Случайные массивы и единичная матрица
import numpy as np
rng = np.random.default_rng(seed=42)
noise = rng.normal(0, 1, size=5) # гауссов шум
eye3 = np.eye(3) # единичная матрица 3x3
print(noise)
print(eye3)
[ 0.30471708 -1.03998411 0.7504512 0.94056472 -1.95103519]
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
Подводные камни
Смешанные типы.
np.array([1, 2.0, 3])дастfloat64— NumPy приведёт всё к общему типу. Если в списке окажется строка, тип станет<U…и арифметика сломается.arange и float-шаг. Из-за погрешностей плавающей точки
np.arange(0, 1, 0.1)может дать 10 или 11 элементов. Для дробных шагов предпочтительнееnp.linspace.empty != zeros. Новички ожидают, что
np.emptyвернёт нули. Это не так — память не инициализируется.Копия или вид.
np.array(other_array)по умолчанию создаёт копию.np.asarray— нет, если тип совпадает. Это важно при работе с большими данными.
См. также
Универсальные функции (ufunc) — операции над массивами
Векторизация в NumPy — ускорение кода без циклов
Модуль numpy.random — генерация случайных данных
Примечание
Лицензия и источники
Техническое описание адаптировано из официальной документации NumPy (https://numpy.org/doc/stable/), доступной под BSD-3-Clause License. Перевод на русский, примеры и пояснения — © AlashEd Wiki.