Главная страница
Навигация по странице:

  • Реорганизация массивов.

  • Создание массивов из других массивов.

  • Логические массивы

  • Работа с элементами массивов.

  • Введение в научный Python-1. Введение в научный Python


    Скачать 6.2 Mb.
    НазваниеВведение в научный Python
    Дата09.01.2020
    Размер6.2 Mb.
    Формат файлаpdf
    Имя файлаВведение в научный Python-1.pdf
    ТипДокументы
    #103229
    страница7 из 22
    1   2   3   4   5   6   7   8   9   10   ...   22
    Векторные и матричные операции над массивами. Одномерные и двумерные массивы интерпретируются как вектора и матрицы, если они используются в качестве аргументов функций, которые вычисляют скалярное или векторное произведение.
    Функция dot() вычисляет скалярное произведение одномерных массивов одинаковой длины.
    >>> np.dot(3, 4)
    # скалярное умножение чисел
    12
    >>> a=np.array([1,2,3,4])
    >>> b=np.array([ -3,-2,-1,0])
    >>> np.dot(a,b)
    # скалярное умножение «векторов»
    -10
    Для двумерных массивов функция dot() выполняет матричное умножение.
    >>> a=np.array([[1,2,3],[4,5,6]])
    >>> print(a)
    [[1 2 3]
    [4 5 6]]
    >>> b=np.array([[1,2],[3,4],[5,6]])
    >>> print(b)
    [[1 2]
    [3 4]
    [5 6]]
    >>> np.dot(a,b)
    # матричное умножение массивов array([[22, 28],
    [49, 64]])

    77
    Массивы имеют метод dot( ), работающий аналогично функции dot( ).
    >>> a=np.array([[1,2],[3, -4]])
    >>> b=np.array([1,3])
    >>> a.dot(b)
    array([ 7, -9])
    Это удобно, когда нужно выполнить подряд несколько операций скалярного произведения, например,
    >>> a.dot(b).dot(b)
    -20
    Функции dot( ) можно передавать аргументы – списки, а не только массивы.
    >>> a=[[-1,3],[4,1]]
    >>> b=[[1,2],[3,4]]
    >>> print(np.dot(a,b))
    [[ 8 10]
    [ 7 12]]
    Однако, списки не имеют метода dot( ).
    Матричное произведение двумерных массивов выполняет также функция matmul()
    , которой можно передавать аргументы – списки. Она появилась в пакете numpy в версии 1.10, и в более ранних версиях вам следует использовать функцию dot.
    >>> np.matmul(a, b) array([[ 8, 10],
    [ 7, 12]])
    Функцию matmul()можно использовать и для вычисления произведения матрицы на вектор.
    >>> b=[1,2]
    >>> np.matmul(a, b)
    array([5, 6])
    >>> np.matmul(b, a) array([7, 5])
    Функция matmul() с аргументами векторами вычисляет скалярное произведение.
    >>> np.matmul([1,2,3],[4,5,6])
    32
    При этом компоненты вектора могут быть комплексными числами.
    >>> np.matmul([2 -1j,3+2j],[5+2j,2-3j])
    (24-6j)
    Функция matmul() отличается от dot() тем, что не вычисляет произведение чисел. Но она умеет вычислять произведение трехмерных массивов, интерпретируя каждый слой таких массивов как матрицу, и вычисляя послойное матричное произведение.
    Для вычисления скалярного произведения векторов можно использовать функцию vdot().
    >>> np.vdot([1,2,3],[4,5,6])
    32

    78
    В отличие от matmul, функция vdot выполняет комплексное сопряжение первого вектора, если его компоненты являются комплексными числами.
    >>> np.vdot([2 -1j,3+2j],[5+2j,2-3j])
    (8-4j)
    Если аргументы функция vdot() являются массивами большей размерности, чем единица, то они (массивы) выравниваются до одномерных.
    >>> a=[[1,2],[3,4]]
    >>> b=[[1, -1],[2,3]]
    >>> np.vdot(a,b)
    17
    Функция cross() вычисляет векторное произведение векторов (одномерных массивов или списков, содержащих три или два элемента)
    >>> x = [1, 2, 3]
    >>> y = [4, 5, 6]
    >>> np.cross(x, y)
    array([-3, 6, -3])
    >>> x = [1, 2]
    >>> y = [4, 5]
    >>> np.cross(x, y)
    array(-3)
    Внешнее произведение векторов (двух одномерных массивов)
    j
    i
    j
    i
    v
    u
    a

    вычисляет функция outer().
    >>> u=np.array([2,3]);
    >>> v=np.array([5,10,15])
    >>> a=np.outer(u,v);print(a)
    [[10 20 30]
    [15 30 45]]
    Тот же результат можно получить с помощью матричного умножения, но для этого вместо одномерных массивов u и v следует использовать двумерные массивы с теми же данными.
    >>> U=np.array([[2,3]]).T; print(U)
    # array.Т – транспонирование массива
    [[2]
    [3]]
    >>> V=np.array([[5,10,15]]);V array([[ 5, 10, 15]])
    >>> np.dot(U, V) array([[10, 20, 30],
    [15, 30, 45]])
    Здесь, чтобы матричное умножение сработало, мы создали матрицу U, состоящую из одного столбца, и матрицу V, состоящую из одной строки.
    Реорганизация массивов. Функция и метод reshape() реорганизовывают массив. Число элементов новой матрицы должно совпадать с числом элементов исходной. При этом данные массива не меняются.
    >>> a=np.arange(0,1,0.25)

    79
    >>> a array([ 0. , 0.25, 0.5 , 0.75])
    >>> b=a.reshape(2,2)
    >>> b array([[ 0. , 0.25],
    [ 0.5 , 0.75]])
    >>> d = np.arange(6).reshape((2,3))
    >>> print(d)
    [[0 1 2]
    [3 4 5]]
    Можно изменить структуру массива, если атрибуту shape присвоить кортеж новых размеров. В этом случае изменится форма массива, но его данные останутся без изменений.
    >>> b=np.arange(4);b array([0, 1, 2, 3])
    >>> b.shape
    (4,)
    >>> b.shape=2,2
    >>> b array([[0, 1],
    [2, 3]])
    Точно также двумерный массив можно сделать одномерным.
    >>> A=np.array([[1,2,3],[4,5,6]]); A array([[1, 2, 3],
    [4, 5, 6]])
    >>> A.shape
    (2, 3)
    >>> A.shape=(6,); A array([1, 2, 3, 4, 5, 6])
    Как видите, присваивание значений атрибуту shape делает то же самое, что и метод reshape().
    Имеется функция resize(a[,new_size]), которая возвращает новый массив, элементами которого являются элементы массива a. Если количество элементов нового массива больше, чем исходного, то новый массив заполняется копиями элементов исходного. Элементы повторяются в том порядке, в котором они хранятся в памяти.
    >>> a=np.array([3,5,7, -2,4])
    >>> np.resize(a,(9,))
    array([ 3, 5, 7, -2, 4, 3, 5, 7, -2])
    >>> a=np.array([[0,1],[2,3]])
    >>> np.resize(a,(2,3))
    array([[0, 1, 2],
    [3, 0, 1]])
    Метод resize(new_size) отличается от функции тем, что новый массив заполняется нулями, а не копиями данных исходного массива.
    >>> b=np.array([8,9,7,5,3])

    80
    >>> b.resize(9)
    >>> b array([8, 9, 7, 5, 3, 0, 0, 0, 0])
    Если на массив имеется другая ссылка, то изменение размера невозможно!
    >>> b=np.array([8,9,7,5,3])
    >>> c=b
    >>> b.resize(9)
    Ошибка!
    Изменение размера массива невозможно также в случае, если до этого он подвергался реорганизации с помощью функции или метода reshape().
    Преобразовать одноэлементный массив в скаляр можно с помощью функции asscalar().
    >>> x=np.array([123]); x array([123])
    >>> y=np.asscalar(x);y
    123
    Метод diagonal() возвращает вектор из диагональных элементов двумерного массива.
    >>> a = np.arange(9).reshape((3,3))
    >>> print(a)
    [[0 1 2]
    [3 4 5]
    [6 7 8]]
    >>> a.diagonal() array([0, 4, 8])
    >>> a = np.arange(6).reshape((2,3))
    >>> print(a)
    [[0 1 2]
    [3 4 5]]
    >>> a.diagonal() array([0, 4])
    Функция transpose() транспонирует массив.
    >>> x=np.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> print(x)
    [[1 2 3]
    [4 5 6]
    [7 8 9]]
    >>> print(np.transpose(x))
    [[1 4 7]
    [2 5 8]
    [3 6 9]]
    У массивов имеется также метод transpose().
    >>> x = np.array([[1,2,3]])
    # двойные квадратные скобки
    >>> x.transpose()

    81 array([[1],
    [2],
    [3]])
    Транспонирование выполняется над массивами размерности больше или равной 2, иначе массив оставляется без изменений. В предыдущем примере мы использовали двойные квадратные скобки для того, чтобы массив x
    был двумерным. Вместо функции и метода transpose() можно использовать атрибут T, который также возвращает транспонированный массив.
    >>> a=np.arange(9).reshape((3,3))
    >>> a.T
    array([[0, 3, 6],
    [1, 4, 7],
    [2, 5, 8]])
    >>> a = np.array([[1],[2],[3]])
    >>> a array([[1],
    [2],
    [3]])
    >>> a.T array([[1, 2, 3]])
    >>> a.T.T array([[1],
    [2],
    [3]])
    Создание массивов из других массивов. Массивы можно конструировать путем объединения уже имеющихся массивов. Функция append()
    «пристраивает» справа к одному массиву другой
    >>> a=np.array([1,2,3])
    >>> a=np.append(a,[10,20,30])
    >>> a array([ 1, 2, 3, 10, 20, 30])
    Функции delete, insert и append не меняют массив, а возвращают новый, в котором удалены, вставлены в середину или добавлены в конец какие-то элементы.
    >>> a=np.arange(2,9,1);print(a)
    [2 3 4 5 6 7 8]
    >>> b=np.delete(a,[2,4]);print(b)
    # [2,4] – индексы удаляемых элементов
    [2 3 5 7 8]
    >>> c=np.insert(a,2,23)
    # вставить на 2-е место число 23
    >>> c array([2,3,23,4,5,6,7,8])
    >>> a=np.arange(2,9,1);print(a)
    [2 3 4 5 6 7 8]
    >>> c=np.insert(a,2,[5,10,15]); print(c)
    # с 2–го индекса вставить 5,10,15
    [ 2 3 5 10 15 4 5 6 7 8]

    82
    >>> np.insert(a,[0,2,5],[11,22,33])
    # [0,2,5] – индексы мест,
    # [11,22,33]) – значения вставляемых элементов array([11, 2, 3, 22, 4, 5, 6, 33, 7, 8])
    По умолчанию многомерные массивы выравниваются до одномерных, а затем выполняется вставка элементов.
    >>> a = np.array([[1, 2], [3, 4], [5, 6]])
    >>> a array([[1, 2],
    [3, 4],
    [5, 6]])
    >>> np.insert(a, 1, 5) array([1, 5, 2, 3, 4, 5, 6])
    Функция hstack() соединяет массивы по горизонтали.
    >>> a=np.arange(2,6,1);print(a)
    [2 3 4 5]
    >>> b=np.arange(10,15,1);print(b)
    [10 11 12 13 14]
    >>> np.hstack((a,b)) array([ 2, 3, 4, 5, 10, 11, 12, 13, 14])
    >>> a = np.array([[1],[2],[3]])
    >>> b = np.array([[5],[6],[7]])
    >>> np.hstack((a,b))
    array([[1, 5],
    [2, 6],
    [3, 7]])
    Функция vstack() соединяет массивы по вертикали.
    >>> a = np.array([1, 2, 3])
    >>> b = np.array([5, 6, 7])
    >>> np.vstack((a,b))
    array([[1, 2, 3],
    [5, 6, 7]])
    >>> a=np.arange(1,7,1).reshape((2,3)); print(a)
    [[1 2 3]
    [4 5 6]]
    >>> b=np.arange(10,70,10).reshape((2,3));print(b)
    [[10 20 30]
    [40 50 60]]
    >>> np.vstack((a,b)) array([[ 1, 2, 3],
    [ 4, 5, 6],
    [10, 20, 30],
    [40, 50, 60]])
    В пакете numpy имеется «оператор» numpy.r_ , предназначенный для конкатенации массивов. Кроме того, его можно использовать для их создания.
    Это не функция, его аргументы следует заключать в квадратные скобки.

    83
    >>> np.r_ [1:10:1]
    # создание массива целых чисел 1≤X<10
    array([1, 2, 3, 4, 5, 6, 7, 8, 9])
    Ессли в команде np.r_ [start:stop:step] параметр step содержит мнимую единицу, т.е. имеет вид Nj, то N представляет количество точек на отрезке
    [start,stop] (а не шаг!), и начальная и конечная точки включаются в массив.
    >>> z=np.r_ [1:4:7j]; z
    # 7 - это количество точек array([1., 1.5, 2., 2.5, 3.,3.5, 4.])
    Если операнды являются массивами (или числами, разделенными запятыми), то они объединяются (по первой оси) в новый массив. В следующей команде мы создаем массив из двух массивов, между которыми вставляем два числа (нули).
    >>> np.r_[np.array([1,2,3]), 0, 0, np.array([4,5,6])] array([1, 2, 3, 0, 0, 4, 5, 6])
    В следующем примере умножение списка на число интерпретируется как повторение списка.
    >>> np.r_[-1:1:5j, [0]*3, 5, 6] array([-1. ,-0.5, 0., 0.5, 1., 0., 0., 0., 5., 6.])
    Если первым аргументом является строка, состоящая из одного символа – цифры, то он интерпретируется как номер оси, по которой будет выполняться конкатенация.
    >>> a = np.array([[ 0, 1, 2], [3, 4, 5]])
    >>> np.r_ ['0', a, a]
    # соединение по 0–ой оси array([[0, 1, 2],
    [3, 4, 5],
    [0, 1, 2],
    [3, 4, 5]])
    >>> np.r_ ['1', a, a]
    # соединение по 1–ой оси array([[0, 1, 2, 0, 1, 2],
    [3, 4, 5, 3, 4, 5]])
    Если первым аргументом является строка „r‟ или „c‟, то результатом конкатенации по строкам (row) или столбцам (column) является матрица.
    >>> np.r_['r',[1,2,3], [4,5,6]] matrix([[1, 2, 3, 4, 5, 6]])
    >>> np.r_['c',[1,2], [5,6]] matrix([[1],
    [2],
    [5],
    [6]])
    Массивы можно расщеплять. Функция hsplit() разделяет массив по горизонтали на несколько подмассивов. Номера столбцов, по которым происходит разрыв, указываются в виде списка вторым аргументом этой функции.
    >>> a=np.arange(9);print(a)
    [0 1 2 3 4 5 6 7 8]
    >>> x,y,z=np.hsplit(a,[2,5])
    >>> print(x); print(y); print(z)

    84
    [0 1]
    [2 3 4]
    [5 6 7 8]
    Если второй аргумент функции hsplit является числом N, то массив делится на N одинаковых по размеру подмассивов. При этом размеры массива и подмассивов должны быть согласованы.
    >>> a = np.arange(8).reshape(2, 4); print(a)
    [[0 1 2 3]
    [4 5 6 7]]
    >>> x,y=np.hsplit(a, 2)
    # разбиение на два подмассива одинакового размера
    >>> print(x)
    [[0 1]
    [4 5]]
    >>> print(y)
    [[2 3]
    [6 7]]
    Функция vsplit() разделяет массив по вертикали на несколько подмассивов.
    Если второй аргумент функции является числом N, то массив делится на N одинаковых по размеру массивов.
    >>> a = np.array([[1,2],[3,4],[5,6],[7,8]])
    >>> print(a)
    [[1 2]
    [3 4]
    [5 6]
    [7 8]]
    >>> x,y=np.vsplit(a,2)
    # разбиение на два подмассива одинакового размера
    >>> print(x)
    [[1 2]
    [3 4]]
    >>> print(y)
    [[5 6]
    [7 8]]
    Если массивы должны иметь различные размеры, то номера строк, по которым будет происходить разбиение, указываются вторым аргументом в квадратных скобках.
    >>> a = np.array([[1,2],[3,4],[5,6]]) ; print(a)
    [[1 2]
    [3 4]
    [5 6]]
    >>> x,y=np.vsplit(a,[1])
    >>> print(x)
    [[1 2]]
    >>> print(y)
    [[3 4]
    [5 6]]
    >>> x,y,z=np.vsplit(a,[1,2])

    85
    >>> print(z)
    [[5 6]]
    Имеются также функции, перемещающие элементы в пределах массива, точнее возвращающие новые массивы, содержащие прежние данные, но в другом порядке. Например, функция roll(x,n) прокручивает вправо элементы массива x на n позиций.
    >>> x = np.arange(9)
    >>> print(x)
    [0 1 2 3 4 5 6 7 8]
    >>> x2=np.roll(x,2)
    >>> print(x2)
    [7 8 0 1 2 3 4 5 6]
    Многомерный массив перед прокручиванием преобразуется в одномерный (в двумерном массиве выравнивание выполняется построчно), а затем его форма восстанавливается.
    >>> x=np.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> print(np.roll(x,2))
    [[8 9 1]
    [2 3 4]
    [5 6 7]]
    Функция sort() возвращает отсортированную копию массива
    >>> a=np.array([5,1, -2,6,0,9])
    >>> b=np.sort(a); print(b)
    [-2 0 1 5 6 9]
    Метод sort() сортирует текущий массив.
    >>> a=np.array([5,1, -2,6,0,9])
    >>> a.sort(); print(a)
    [-2 0 1 5 6 9]
    В двумерных массивах данные сортируются в каждой строке
    >>> b=np.array([[2,5,0],[4,1,3]])
    >>> print(np.sort(b))
    [[0 2 5]
    [1 3 4]]
    Логические массивы. Логические (булевы) массивы состоят из логических элементов True и False.
    >>> a = np.array([True, False, True, False])
    >>> a array([True,False, True,False],dtype=bool)
    >>> b = np.array([1, 1, 0, 0], dtype=bool)
    >>> b array([True, True, False, False], dtype=bool)
    Обычно логические массивы создаются при выполнении операций сравнения.
    >>> x=np.array([ -3.5, 2.2, -5.1, 4.3, 6.8, -8.0, 4.0])
    >>> y=np.array([4.5, 2.2, -2.1, 4.3, 7.8, -1.0, 4.0])
    >>> Z=x==y

    86
    >>> Z array([False, True, False, True, False, False, True],dtype=bool)
    >>> X=x<0
    >>> X
    array([True, False, True, False, False, True, False],dtype=bool)
    Двойное неравенство для массивов не работает.
    >>> -3Ошибка!
    Для сложных условий следует использовать функции пакета numpy, которые реализуют операции логической алгебры для массивов: logical_and(), logical_or(), logical_xor(), logical_not(). Например, последнее неравенство можно записать в виде
    >>> np.logical_and(x>=-3,x<6) array([False,True,False,True,False,False,True],dtype=bool)
    Вот более сложное логическое условие
    >>> np.logical_not(np.logical_or(x>0,y>2)) array([False,False,True,False,False,True,False],dtype=bool)
    Функция any(логический_массив) пакета numpy возвращает True, если хотя бы один из элементов логического_массива равен True.
    >>> np.any(X)
    True
    Функция all(логический_массив) возвращает True, если все элементы логического_массива равны True.
    >>> np.all(X)
    False
    >>> a = np.array([1, -2, 3, -1])
    >>> b = np.array([2, 2, 3, 2])
    >>> c = np.array([6, 4, 7, 5])
    >>> ((a <= b) & (b <= c)).all()
    True
    Функция array_equal(arr1, arr2) возвращает True или False в зависимости от того совпадают ли значения элементов массива arr1 с соответствующими элементами массива arr2.
    >>> np.array_equal(a,b)
    False
    >>> d=np.array([4,1,6,2]) -3
    >>> np.array_equal(a,d)
    True
    Работа с элементами массивов. Доступ к элементам массива осуществляется с использованием индексации. При этом можно использовать список индексов.
    >>> a = np.arange(6)
    >>> print(a[[1,3,5]])
    [ 1. 3. 5.]
    Имеется возможность логической индексации. Для этого используются булевы массивы.

    87
    >>> a=np.array([2,-1,3,4,-5,7,-2,6,-7]); print(a)
    [ 2 -1 3 4 -5 7 -2 6 -7]
    >>> b=a>0; print(b)
    # массив b является логическим
    [True False True True False True False True False]
    Логическая индексация имеет следующий формат: основной_массив[логический_массив], где логический массив должен иметь тот же размер, что и основной.
    Результатом этой операции является массив, составленный из элементов основного массива, для которых в логическом массиве соответствующие элементы равны True.
    >>> c=a[b]; print(c)
    [2 3 4 7 6]
    Пусть из двумерного массива B требуется выбрать все отрицательные элементы и записать их в одномерный массив F.
    >>> B=np.array([[4, -3, -1],[ 2, 7, 0],[ -5, 1, -2]]); print(B)
    [[ 4 -3 -1]
    [ 2 7 0]
    [-5 1 -2]]
    Сначала создадим логический массив.
    >>> ind=B<0; print(ind)
    [[False True True]
    [False False False]
    [ True False True]]
    Использование логического массива ind в качестве индекса исходного массива
    B
    позволяет решить поставленную задачу
    >>> F=B[ind]; print(F)
    [-3 -1 -5 -2]
    Можно было обойтись и без вспомогательного массива ind, написав сразу
    >>> F = B[B<0]; print(F)
    [-3 -1 -5 -2]
    Аналогично
    >>> A=np.arange( -3,6).reshape(3,3);print(A)
    [[-3 -2 -1]
    [ 0 1 2]
    [ 3 4 5]]
    >>> C=A[A>B]; print(C)
    [-2 2 3 4 5]
    Логическое индексирование позволяет выбрать из массива элементы, удовлетворяющие определенным условиям, которые заданы логическим выражением.
    Если требуется присвоить новое значение элементам массива, удовлетворяющим определенному условию, то массив с логическим индексом должен войти в левую часть оператора присваивания.
    >>> A=np.arange(1,10).reshape(3,3);print(A)

    88
    [[1 2 3]
    [4 5 6]
    [7 8 9]]
    >>> B=np.array([[8,1,6],[3,5,7],[4,9,2]]); print(B)
    [[8 1 6]
    [3 5 7]
    [4 9 2]]
    >>> C=A<=B; print(C)
    [[ True False True]
    [False True True]
    [False True False]]
    >>> A[C]=0; print(A)
    [[0 2 0]
    [4 0 0]
    [7 0 9]]
    1   2   3   4   5   6   7   8   9   10   ...   22


    написать администратору сайта