Каждая ошибка показана парой: как не надо и как надо. Подробности — в статье по ссылке.
a = np.array([1, 2, 3])
b = np.array([1, 2, 3])
temps = np.array([3.0, -2.0, np.nan, 8.0])Массив в условии if
a == b возвращает массив, а не одно значение. → Сравнение массивов
if a == b:
print("равны")ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
if np.array_equal(a, b):
print("равны")равны
and / or вместо & / |
С массивами работают только &, |, ~, а каждое условие берётся в скобки. → Булевы маски
temps[(temps > 0) and (temps < 5)]ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
temps[(temps > 0) & (temps < 5)]array([3.])
Изменение среза меняет исходный массив
Срез — представление, а не копия. → Представления и копии
first_two = a[:2]
first_two[0] = 100 # хотели изменить только копию
aarray([100, 2, 3])
first_two = a[:2].copy()
first_two[0] = 100
aarray([1, 2, 3])
result = a.sort()
Метод сортирует на месте и возвращает None. → Сортировка
result = a.sort()
print(result)None
result = np.sort(np.array([3, 1, 2]))
resultarray([1, 2, 3])
Поиск NaN через ==
temps[temps == np.nan] # пусто: NaN не равен ничемуarray([], dtype=float64)
temps[np.isnan(temps)]array([nan])
Переполнение маленьких целых типов
Арифметика не проверяет выход за пределы типа. → Типы данных
pixels = np.array([200, 100], dtype=np.uint8)
pixels + 100 # 300 не помещается в uint8array([ 44, 200], dtype=uint8)
pixels = np.array([200, 100], dtype=np.uint8)
pixels.astype(np.int64) + 100array([300, 200])
Вектор (n,) вместо столбца (n, 1)
Для квадратной матрицы ошибки нет, но результат неверный. → Транслирование
m = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]])
m - m.mean(axis=1) # ошибки нет, но вычтено по столбцамarray([[-1., -3., -5.],
[ 2., 0., -2.],
[ 5., 3., 1.]])m = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]])
m - m.mean(axis=1, keepdims=True)array([[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.]])Дробное значение в целом массиве
При записи значение приводится к типу массива. → Типы данных
counts = np.array([1, 2, 3])
counts[0] = 2.7 # дробная часть молча отброшена
countsarray([2, 2, 3])
counts = np.array([1, 2, 3], dtype=float)
counts[0] = 2.7
countsarray([2.7, 2. , 3. ])
Форма без скобок
np.zeros(2, 3)TypeError: Cannot interpret '3' as a data type
np.zeros((2, 3))array([[0., 0., 0.],
[0., 0., 0.]])Функции math для массивов
import math
math.sqrt(np.array([4.0, 9.0]))TypeError: only 0-dimensional arrays can be converted to Python scalars
np.sqrt(np.array([4.0, 9.0]))array([2., 3.])
Разное std в NumPy и pandas
np.std(np.array([2.0, 4.0, 6.0])) # ddof=0, а pandas даст другое числоnp.float64(1.632993161855452)
np.std(np.array([2.0, 4.0, 6.0]), ddof=1) # как Series.std() в pandasnp.float64(2.0)
Цикл вместо операции над массивом
Цикл Python по элементам и np.vectorize в десятки раз медленнее векторных операций. Перепишите через np.where, np.select, агрегации с axis и транслирование. → Векторизация