На этом шаге мы приведем код и поясним принцип его работы.
Итак, имеются данные по многим специальностям, и нужно повышать зарплаты одних только исследователей данных на 10% раз в два года. Соответствующий код приведен в примере 3.11.
Задумайтесь на минуту о результатах выполнения этого фрагмента кода. Как вы думаете, что изменится? Какой тип данных будет у полученного в результате массива? Что выведет данный код?
## Зависимости import numpy as np ## Данные: годовые зарплаты в тысячах долларов (за 2025, 2026 и 2027 гг.) dataScientist = [130, 132, 137] productManager = [127, 140, 145] designer = [118, 118, 127] softwareEngineer = [129, 131, 137] employees = np.array([dataScientist, productManager, designer, softwareEngineer]) ## Однострочник employees[0, ::2] = employees[0, ::2] * 1.1 ## Результат print(employees)
В этом фрагменте кода вы попадаете в 2024 год. Во-первых, вы создаете массив NumPy, каждая строка которого содержит ожидаемую годовую зарплату одного специалиста (исследователя данных, руководителя по программному продукту, дизайнера или разработчика программного обеспечения). А каждый столбец отражает соответствующие годовые зарплаты за 2025, 2026 и 2027 годы. Полученный в результате массив NumPy включает четыре строки и три столбца.
Вы нашли средства, чтобы поощрить самых важных специалистов в компании. Вы верите в будущее data science, поэтому решили вознаградить незаметных героев вашей компании: исследователей данных. Вам нужно обновить массив NumPy так, чтобы только зарплаты исследователей данных возрастали на 10% через год (без капитализации процентов) начиная с 2025 года.
Вы разработали следующий замечательный однострочник:
employees[0,::2] = employees[0,::2] * 1.1
Он выглядит просто и аккуратно, а результаты его работы - следующие:
[[143 132 150] [127 140 145] [118 118 127] [129 131 137]]
Несмотря на свою простоту, однострочник использует три интересных продвинутых понятия.
Во-первых, мы воспользуемся срезами и присваиванием срезам. В этом примере с помощью среза мы извлечем каждое второе значение из первой строки массива
NumPy employees. Далее выполним некоторые модификации и обновим каждое второе значение первой строки с помощью присваивания срезу. Синтаксис
присваивания срезу не отличается от самого среза, за исключением одного важного нюанса: в этом случае срез указывается с левой стороны оператора присваивания.
Соответствующие элементы будут заменены элементами, указанными справа от оператора присваивания. В представленном фрагменте кода мы заменяем содержимое
первой строки массива NumPy обновленными данными о зарплатах.
Во-вторых, мы воспользуемся транслированием для автоматического исправления поэлементных операций над массивами NumPy различной формы. В нашем однострочнике левый операнд - массив NumPy, а правый - значение с плавающей точкой. Опять же, NumPy автоматически создает новый массив того же размера и размерности, что и массив слева от оператора присваивания, и заполняет его, по сути, копиями этого значения с плавающей точкой. Фактически NumPy производит вычисление наподобие следующего:
np.array([130 137]) * np.array([1.1, 1.1])
В-третьих, наверное, вы поняли, что тип данных результата - не float, а integer, даже если вы выполняете операции над числами с плавающей точкой. При создании массива NumPy понимает, что тот содержит только целочисленные значения, поэтому полагает, что массив должен быть типа integer. Никакие операции над массивом типа integer не меняют типа данных, вследствие чего NumPy будет округлять значения до целочисленных. Опять же, узнать тип массива можно с помощью свойства dtype:
print(employees.dtype) # int32 employees[0,::2] = employees[0,::2] * 1.1 print(employees.dtype) # int32
Итак, вы узнали о срезах, присваивании срезам, транслировании и типах массивов NumPy - впечатляющее достижение для однострочного фрагмента кода. Закрепим достигнутый успех, решив небольшую, но практичную задачу исследования данных: выявление аномальных значений в измерениях загрязнений для различных городов.
На следующем шаге мы рассмотрим обнаружение аномальных значений с помощью условного поиска по массиву, фильтрации и транслирования.