Занятие 3

Лабораторная работа 3

NumPy(сокращенно от Numerical Python)— библиотека с открытым исходным кодом для языка программирования Python.

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

NumPy обеспечивает как гибкость Python, так и скорость хорошо оптимизированного скомпилированного кода на C.

Если у вас ещё не установлен Numpy это можно сделать командой: pip install numpy

0. Массивы в Numpy

  • Массив в NumPy это таблица элементов одного типа, пронумерованная кортежем положительных целых чисел.
  • В NumPy измерения называются осями. Количество осей является рангом.
  • Класс массива NumPy называется ndarray.

Обратите внимание, что массив в Numpy содержит элементы одного типа, в отличие от списка!

In [77]:
import numpy as np # импортируем библиотеку и заменим её ключевым словом np(для удобства)
In [78]:
arr1 = np.array([1, 2, 3]) # массив ранга 1
arr2 = np.array( [[1, 2, 3], [4, 2, 5]] ) # массив ранга 2(матрица с двумя строками и тремя столбцами)

1. Создание массива

Есть несколько способов создать массив NumPy. Рассмотрим их подробнее:

1.1 Функция array

Вы можете создать массив из обычного списка или кортежа, используя array().

In [79]:
a = np.array([[1, 2, 3], [4, 5, 6]], dtype = 'int')
print(a)
[[1 2 3]
 [4 5 6]]

1.2. Создание массива заполнением начальными значениями

Допустим нам неизвестны элементы массива, но известен его размер. В NumPy существуют функции для создания массивов с начальным заполнением.

In [80]:
a = np.zeros(5) # создаём 1-d массив, содержащий 5 нулей
print('a:', a)
b = np.zeros((2, 3)) # создаём 2-d массив, размера 2 на 3
print('b:', b)
r = np.random.random(5) # создаём массив со случайными значениями на определённом интервале
print('r:', r)
a: [0. 0. 0. 0. 0.]
b: [[0. 0. 0.]
 [0. 0. 0.]]
r: [0.19344404 0.7833302  0.1850033  0.71576896 0.48646674]

1.3. Фунция arange

In [81]:
a = np.arange(0, 10, 2) # создаём массив от 0 до 10 с шагом 2
print(a)
[0 2 4 6 8]

1.4. reshape

Мы также можем менять размеры массивов. Размер массива всегда можно вычислить командой a.shape

In [82]:
a = np.array([[1, 2, 3, 4], [5, 2, 4, 2]])
print('a: ', a.shape)
new_a = a.reshape(4, 2)
print('new_a: ', new_a.shape)
a:  (2, 4)
new_a:  (4, 2)

1.5. flatten

Любой многомерный массив мы можем развернуть с помощью функции flatten.

In [83]:
a = np.array([[1, 2, 3, 4], [5, 2, 4, 2]])
new_a = a.flatten()
print(new_a)
[1 2 3 4 5 2 4 2]

2. Идексация массивов

2.1 Одномерных

In [84]:
a = np.arange(10) # создадим массив
print(a)
[0 1 2 3 4 5 6 7 8 9]
In [85]:
# как можно заменить доступ остался таким же как в списках
print('четвёртый элемент:', a[3])
print('последний элемент:', a[-1])
a[3] = 11
print('теперь четвёртый элемент:', a[3])
четвёртый элемент: 3
последний элемент: 9
теперь четвёртый элемент: 11
In [86]:
# мы также можем создавать срезы, как и в списках.
new_a = a[1:5]
In [87]:
# теперь немного магии
new_a[1] = -10
print(a)
[  0   1 -10  11   4   5   6   7   8   9]

Мы поменяли элемент среза и наш исходный массив тоже изменился!!! Почему? Это сделано специально для экономии памяти. Данные на которые ссылаются a и new_a одни и те же. Срезы – это не полноценные копии массивов, а скорее их новое представление.

2.2 Многомерных

In [88]:
x = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)]) # создаём многомерный массив

С точки зрения математики, можно сказать, что нашим объектом является следующая матрица.

\begin{equation} \begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9 \end{bmatrix} \label{eq:aeqn} \end{equation}
In [89]:
#мы также можем обращаться к элементам матрицы следующим образом
print(x[2][2])
# можем обратиться только к конкретной строке 
print(x[0])
# к конкретному столбцу
print(x[:,0])
9
[1 2 3]
[1 4 7]

Итерирование многомерных массивов можно выполнять с помощью вложенных циклов.

In [90]:
for row in x:
    for value in row:
        print(value, end=' ')
    print()
1 2 3 
4 5 6 
7 8 9 

Можно использовать flat, позволяющий выводить элементы многомерного массива поэлемента.

In [91]:
for val in x.flat:
    print(val, end=' ')
1 2 3 4 5 6 7 8 9 

3. Операции над массивами

3.1 Математические операции

In [92]:
# создадим два массива
a = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)])
b = np.array([(19, 20, 21), (22, 23, 24), (25, 26, 27)])

Мы можем складывать, умножать, делить, считать остаток и т.д поэлементно.

In [93]:
# сумма
print(a + b)
[[20 22 24]
 [26 28 30]
 [32 34 36]]
In [94]:
# разность
print(a - b)
[[-18 -18 -18]
 [-18 -18 -18]
 [-18 -18 -18]]
In [95]:
# умножение
print(a * b)
[[ 19  40  63]
 [ 88 115 144]
 [175 208 243]]
In [96]:
# остаток от деления
print(b % a)
[[0 0 0]
 [2 3 0]
 [4 2 0]]
In [97]:
# Также, в numpy есть библиотека стандартных мат функций, которые можно применить к каждому элементу массива. 
a = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)])
np.sqrt(a)
Out[97]:
array([[1.        , 1.41421356, 1.73205081],
       [2.        , 2.23606798, 2.44948974],
       [2.64575131, 2.82842712, 3.        ]])

3.2 Базовые операции с массивыми

In [98]:
a = np.array([(1, 2, 3, 4, 5, 6, 7, 8, 9)])
# сумма элементов
print(a.sum())
# произведение элементов
print(a.prod())
# макс и мин элемент
print(a.max())
print(a.min())
# среднее значение
print(a.mean())
# дисперсия
print(a.var())
45
362880
9
1
5.0
6.666666666666667

P.S NumPy - мощный интсрумент, который содержит в себе много функций и методов.

Обращайтесь к туториалу: https://numpy.org/devdocs/user/quickstart.html

И не бойтесь гуглить!

Задача 1

Создайте две numpy матрицы, содержащие температуры в Кельвинах и Фаренгейтах на основе матрицы температур в Цельсиях.

In [99]:
a = np.array([(14, 23, 31, 14, 55, 36, 87, 118, 91)]) # матрица температур(в Цельсиях)
In [ ]:

Задача 2

Создайте матрицу с 0 внутри и 1 на границах.

In [ ]:

3.3 Умножения матриц

In [100]:
a = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)])
a = np.array([(1), (4), (7)])
# можем так
print(a @ b)
# а можем так
print(a.dot(b))
[282 294 306]
[282 294 306]

Задача 3

Посчитайте произведение матриц используя:

  • @
  • dot
  • не используя ни dot, ни @
In [101]:
A = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])
B = np.array([[11.0, 12.0],
              [13.0, 14.0],
              [15.0, 16.0]])
In [ ]:

Задача 4

Мы можем расчитать норму вектора: np.linalg.norm([1.0, 2.0, 3.0]).

Найдите косинус угла между векторами:

  • используя np.linalg.norm
  • не используя
In [102]:
a = np.array([1.0, 2.0, 3.0])
b = np.array([4.0, 5.0, 6.0])
In [ ]:

4. Линейнай алгебра в NumPy

4.1 Решение систем линейных уравнений

Библиотеку numpy удобно использовать для решения систем линейных уравнений. Если система уравнений $Ax = y$ имеет решение, и при этом только одно, то оно выражается как $x = A^{-1}y$ . Для обращения матрицы используется функция np.linalg.inv. Рассмотрим систему уравнений: $$ \left\{ \begin{array}{c} 2x + z = 1 \\ x - z = 4 \\ \end{array} \right. $$

In [103]:
A = np.array([[2.0, 1.0],
              [1.0, -1.0]])
y = np.array([1.0, 4.0])
# решение будет
print(np.linalg.inv(A) @ y)
[ 1.66666667 -2.33333333]

Задача 5

Решите следующую систему:

$$ \left\{ \begin{array}{c} 2x+3y+4z = 5 \\ x-y+z=3 \\ 2x+6y-3z=4 \end{array} \right. $$
In [ ]:

4.2 Ещё немного линейной алгебры

Задача 6

Дана матрица B.

Найдите её:

  • детерминант
  • ранг
  • собственные значения

P.S воспользуйтесь полезным туториалом: https://www.geeksforgeeks.org/numpy-linear-algebra/?ref=lbp.

In [104]:
B = np.array([[11.0, 12.0],
              [13.0, 14.0],
              [15.0, 16.0]])
In [ ]:

5. Математика многочленов

5.1 np.poly

In [105]:
# np.poly - передаём список корней, получаем коэффициенты уравнения, которое имеет данные корни:
np.poly([-1, 1, 2])
Out[105]:
array([ 1., -2., -1.,  2.])

Получили уравнение:

$x^3 -2x^2 -x + 2 =0$

5.2 roots

In [106]:
# np.roots - передаём список коэффициентов уравнения, возвращаем корни.
np.roots([1, -5, 6])
Out[106]:
array([3., 2.])

Мы решили уравнение: $x^2 - 5x + 6 = 0$

Задача 7

Напишите функцию решающую квадратное уравнение и принимающую на вход коэффициенты этого уравнения.

In [ ]:

Задача 8

Теперь решите задачу 7, не используя np.roots.

Почувствуйте разницу)

In [ ]:

6. Разные задачки

P.S При решении рекомендуется обращаться к руководству пользователя NumPy: https://numpy.org/doc/stable/user/index.html

Задача 9

Дан массив a. Поменяйте знак у элементов, кратных трём.

In [ ]:
a = np.arange(20)
In [ ]:

Задача 10

Дано 4 точки у каждой из которых есть координата x и y. Значения x и y каждой точки представлены в матрице A.

Преобразуйте их в полярные координаты.

In [72]:
A = np.array([[1,1],[1,0], [0,1], [0,0]]).astype(float)
In [ ]:

Задача 11

Напишите функцию, которая определяет есть ли в 2D массиве нулевые столбцы.

In [ ]:

Задача 12

Найдите наиболее частое значение в массиве.

In [ ]:

Задача 13

Найдите наиболее частое значение в массиве.

In [ ]:

Задача 14(2 балла)

Создайте класс Matrix, добавьте в него методы сложения, умножения, транспонирования, возведения в степень.

In [ ]:

Задача 15

Пусть дано n, матрица A. Напишите функцию, вычисляющую ряд: $A + A^2 + ... A^n$.

In [ ]: