Как изменить размерность массива numpy

method

method

ndarray.resize(new_shape, refcheck=True)#

Change shape and size of array in-place.

Parameters:
new_shapetuple of ints, or n ints

Shape of resized array.

refcheckbool, optional

If False, reference count will not be checked. Default is True.

Returns:
None
Raises:
ValueError

If a does not own its own data or references or views to it exist,
and the data memory must be changed.
PyPy only: will always raise if the data memory must be changed, since
there is no reliable way to determine if references or views to it
exist.

SystemError

If the order keyword argument is specified. This behaviour is a
bug in NumPy.

See also

resize

Return a new array with the specified shape.

Notes

This reallocates space for the data area if necessary.

Only contiguous arrays (data elements consecutive in memory) can be
resized.

The purpose of the reference count check is to make sure you
do not use this array as a buffer for another Python object and then
reallocate the memory. However, reference counts can increase in
other ways so if you are sure that you have not shared the memory
for this array with another Python object, then you may safely set
refcheck to False.

Examples

Shrinking an array: array is flattened (in the order that the data are
stored in memory), resized, and reshaped:

>>> a = np.array([[0, 1], [2, 3]], order='C')
>>> a.resize((2, 1))
>>> a
array([[0],
       [1]])
>>> a = np.array([[0, 1], [2, 3]], order='F')
>>> a.resize((2, 1))
>>> a
array([[0],
       [2]])

Enlarging an array: as above, but missing entries are filled with zeros:

>>> b = np.array([[0, 1], [2, 3]])
>>> b.resize(2, 3) # new_shape parameter doesn't have to be a tuple
>>> b
array([[0, 1, 2],
       [3, 0, 0]])

Referencing an array prevents resizing…

>>> c = a
>>> a.resize((1, 1))
Traceback (most recent call last):
...
ValueError: cannot resize an array that references or is referenced ...

Unless refcheck is False:

>>> a.resize((1, 1), refcheck=False)
>>> a
array([[0]])
>>> c
array([[0]])

Improve Article

Save Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Let’s discuss how to change the dimensions of an array. In NumPy, this can be achieved in many ways. Let’s discuss each of them. 

    Method #1: Using Shape()

    Syntax :

    array_name.shape()

    Python3

    import numpy as np

    def main():

        print('Initialised array')

        gfg = np.array([1, 2, 3, 4])

        print(gfg)

        print('current shape of the array')

        print(gfg.shape)

        print('changing shape to 2,2')

        gfg.shape = (2, 2)

        print(gfg)

    if __name__ == "__main__":

        main()

    Output:

    Initialised array
    [1 2 3 4]
    current shape of the array
    (4,)
    changing shape to 2,2
    [[1 2]
     [3 4]]

    Method #2: Using reshape()

    The order parameter of reshape() function is advanced and optional. The output differs when we use C and F because of the difference in the way in which NumPy changes the index of the resulting array. Order A makes NumPy choose the best possible order from C or F according to available size in a memory block.

    Difference between Order C and F

    Syntax :

    numpy.reshape(array_name, newshape, order= 'C' or 'F' or 'A')

    Python3

    import numpy as np

    def main():

        gfg = np.arange(1, 10)

        print('initialised array')

        print(gfg)

        print('3x3 order C array')

        print(np.reshape(gfg, (3, 3), order='C'))

        print('3x3 order F array')

        print(np.reshape(gfg, (3, 3), order='F'))

        print('3x3 order A array')

        print(np.reshape(gfg, (3, 3), order='A'))

    if __name__ == "__main__":

        main()

    Output :

    initialised array
    [1 2 3 4 5 6 7 8 9]
    3x3 order C array
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    3x3 order F array
    [[1 4 7]
     [2 5 8]
     [3 6 9]]
    3x3 order A array
    [[1 2 3]
     [4 5 6]
     [7 8 9]]

    Method #3 : Using resize()

    The shape of the array can also be changed using the resize() method. If the specified dimension is larger than the actual array, The extra spaces in the new array will be filled with repeated copies of the original array.

    Syntax :

    numpy.resize(a, new_shape)

    Python3

    import numpy as np

    def main():

        gfg = np.arange(1, 10)

        print('initialised array')

        print(gfg)

        gfg1=np.resize(gfg, (3, 3))

        print('3x3 array')

        print(gfg1)

        gfg2=np.resize(gfg, (4, 4))

        print('4x4 array')

        print(gfg2)

        gfg.resize(5, 5)

        print('5x5 array')

        print(gfg)

    if __name__ == "__main__":

        main()

    Output :

    initialised array
    [1 2 3 4 5 6 7 8 9]
    3x3 array
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    4x4 array
    [[1 2 3 4]
     [5 6 7 8]
     [9 1 2 3]
     [4 5 6 7]]
    5x5 array
    [[1 2 3 4 5]
     [6 7 8 9 0]
     [0 0 0 0 0]
     [0 0 0 0 0]
     [0 0 0 0 0]]

    Improve Article

    Save Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Let’s discuss how to change the dimensions of an array. In NumPy, this can be achieved in many ways. Let’s discuss each of them. 

    Method #1: Using Shape()

    Syntax :

    array_name.shape()

    Python3

    import numpy as np

    def main():

        print('Initialised array')

        gfg = np.array([1, 2, 3, 4])

        print(gfg)

        print('current shape of the array')

        print(gfg.shape)

        print('changing shape to 2,2')

        gfg.shape = (2, 2)

        print(gfg)

    if __name__ == "__main__":

        main()

    Output:

    Initialised array
    [1 2 3 4]
    current shape of the array
    (4,)
    changing shape to 2,2
    [[1 2]
     [3 4]]

    Method #2: Using reshape()

    The order parameter of reshape() function is advanced and optional. The output differs when we use C and F because of the difference in the way in which NumPy changes the index of the resulting array. Order A makes NumPy choose the best possible order from C or F according to available size in a memory block.

    Difference between Order C and F

    Syntax :

    numpy.reshape(array_name, newshape, order= 'C' or 'F' or 'A')

    Python3

    import numpy as np

    def main():

        gfg = np.arange(1, 10)

        print('initialised array')

        print(gfg)

        print('3x3 order C array')

        print(np.reshape(gfg, (3, 3), order='C'))

        print('3x3 order F array')

        print(np.reshape(gfg, (3, 3), order='F'))

        print('3x3 order A array')

        print(np.reshape(gfg, (3, 3), order='A'))

    if __name__ == "__main__":

        main()

    Output :

    initialised array
    [1 2 3 4 5 6 7 8 9]
    3x3 order C array
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    3x3 order F array
    [[1 4 7]
     [2 5 8]
     [3 6 9]]
    3x3 order A array
    [[1 2 3]
     [4 5 6]
     [7 8 9]]

    Method #3 : Using resize()

    The shape of the array can also be changed using the resize() method. If the specified dimension is larger than the actual array, The extra spaces in the new array will be filled with repeated copies of the original array.

    Syntax :

    numpy.resize(a, new_shape)

    Python3

    import numpy as np

    def main():

        gfg = np.arange(1, 10)

        print('initialised array')

        print(gfg)

        gfg1=np.resize(gfg, (3, 3))

        print('3x3 array')

        print(gfg1)

        gfg2=np.resize(gfg, (4, 4))

        print('4x4 array')

        print(gfg2)

        gfg.resize(5, 5)

        print('5x5 array')

        print(gfg)

    if __name__ == "__main__":

        main()

    Output :

    initialised array
    [1 2 3 4 5 6 7 8 9]
    3x3 array
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    4x4 array
    [[1 2 3 4]
     [5 6 7 8]
     [9 1 2 3]
     [4 5 6 7]]
    5x5 array
    [[1 2 3 4 5]
     [6 7 8 9 0]
     [0 0 0 0 0]
     [0 0 0 0 0]
     [0 0 0 0 0]]

    На предыдущем
    занятии мы немного познакомились со способами изменения формы массивов пакета NumPy, то есть
    изменением их размерностей. На этом занятии поближе рассмотрим эту тему и
    познакомимся с наиболее употребительными функциями и свойствами, влияющих на
    представление массивов.

    Изменение размерности массивов

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

    a = np.arange(10)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    Мы уже знаем,
    что для изменения формы этого массива, достаточно указать свойству shape кортеж с новыми
    размерами, например, так:

    a.shape = 2, 5   # массив размерностью 2x5

    В результате
    изменится представление массива, на которое ссылается переменная a. Если же
    требуется создать новое представление массива, сохранив прежнее, то следует
    воспользоваться методом reshape():

    b = a.reshape(10)  # массив [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    И, как мы с вами
    говорили на предыдущем занятии, ссылки b и a будут использовать
    одни и те же данные, то есть, изменение массива через b:

    приведет к
    изменению соответствующего элемента массива a:

    array([[-1,  1,  2,  3,  4],

           [ 5,  6, 
    7,  8,  9]])

    Об этом всегда
    следует помнить. Также следует помнить, что у свойства shape и метода reshape() размерность
    должна охватывать все элементы массива. Например, вот такая команда:

    приведет к
    ошибке, т.к. размерность 3×3 = 9 элементов, а в массиве 10
    элементов. Здесь всегда должно выполняться равенство:

    n1 x n2 x … x nN = число
    элементов массива

    Но допускается
    делать так:

    a.shape = -1, 2  # размерность 5x2

    Отрицательное
    значение -1 означает автоматическое вычисление размерности по первой оси. По
    второй берется значение 2. В этом случае получим размерность 5×2.

    То же самое
    можно делать и в методе reshape():

    b.reshape(-1, 1) # размерность 10x1
    b.reshape(1, -1) # размерность 1x10

    Обратите
    внимание, в последних двух случаях мы получаем представления двумерных
    массивов, преобразуя одномерный. Это важный момент, так как на выходе метода reshape() получается
    матрица с двумя осями (строки и столбцы), тогда как изначально массив b имел только
    одну ось. Не случайно последнее представление отображается с двумя квадратными
    скобками:

    array([[-1,  1,  2, 
    3,  4,  5,  6,  7,  8,  9]])

    Первая скобка –
    это первая ось (строка), а вторая скобка (вторая ось) описывает столбцы. Одномерный
    же массив b отображается с
    одной квадратной скобкой:

    array([-1,  1, 
    2,  3,  4,  5,  6,  7,  8,  9])

    Используя
    отрицательный индекс, можно делать и такие преобразования:

    b.reshape(2, -1)  # размерность 2x5
    b.reshape(-1, 2)  # размерность 5x2

    Первое
    представление (2×5) отображается следующим образом:

    array([[-1, 
    1,  2,  3,  4],

           [ 5,  6, 
    7,  8,  9]])

    Здесь снова мы
    видим две квадратные скобки (значит, массив двумерный). Первая описывает ось axis0, отвечающую за
    строки, а вложенные скобки описывают вторую ось axis1, отвечающую за
    столбцы.

    Если нам
    требуется многомерный массив преобразовать в обычный одномерный, то можно
    воспользоваться методом ravel(), который возвращает новое
    представление, не меняя текущего:

    c = b.ravel() # с ссылается на одномерное представление массива

    Если же нам
    нужно текущий массив преобразовать в одномерный, то это можно сделать так:

    Помимо свойства shape можно
    использовать метод resize, который выполняет подобную операцию с
    текущим массивом. Например:

    a.resize(2, 5) # массив 2x5

    Но, как мы уже
    говорили, вот такая строчка приведет к ошибке:

    a.resize(3, 3)  # ошибка: 3x3 != 10

    Однако, мы
    все-таки можем выполнить такую операцию, указав дополнительно флаг refcheck=False:

    a.resize(3, 3, refcheck=False)  # массив 3x3

    или так:

    a.resize(4, 5, refcheck=False) # массив 4x5

    В первом случае
    происходит удаление одного 10-го элемента, а во втором случае – добавление
    4∙5 — 3∙3 = 11 нулей. Это очень удобно, когда нам нужно менять не
    только форму, но и размер самого массива.

    Транспонирование матриц и векторов

    Очень часто в
    математических операциях требуется выполнять транспонирование матриц и
    векторов, то есть, заменять строки на столбцы. Например, если имеется матрица
    (двумерный массив):

    a = np.array([(1, 2, 3), (1, 4, 9), (1, 8, 27)])

    то операция
    транспонирования может быть реализована так:

    Обратите
    внимание, мы здесь создаем лишь новое представление тех же самых данных массива
    a. И изменение
    элементов в массиве b:

    приведет к
    соответствующему изменению значения элемента и массива a. Это следует
    помнить, используя операцию транспонирования.

    Транспонирование
    векторов работает несколько иначе. Предположим, имеется одномерный массив:

    и мы выполняем
    операцию транспонирования:

    В результате
    ничего не изменилось: вектор как был строкой, так строкой и остался. Почему?
    Дело в том, что массив x имеет только
    одну размерность, поэтому здесь нет понятия строк и столбцов. Соответственно,
    операция транспонирования ни к чему не приводит. Чтобы получить ожидаемый
    эффект, нужно добавить к массиву еще одну ось, например, так:

    И теперь, при
    транспонировании получим вектор-столбец:

    Добавление и удаление осей

    Часто при работе
    с массивами NumPy требуется
    добавлять новые оси измерений и удалять существующие. Есть множество способов
    выполнять эти операции, но мы рассмотрим два наиболее распространенных с
    помощью функций:

    • np.expand_dims(a,
      axis) – добавление
      новой оси;

    • np.squeeze(a[, axis]) – удаление
      оси (без удаления элементов).

    Давайте
    предположим, что у нас имеется некий многомерный массив:

    x_test = np.arange(32).reshape(8, 2, 2) # массив 8x2x2

    И нам
    потребовалось добавить еще одно измерение (ось), причем, в самое начало, то
    есть, ось axis0. Сейчас на
    этой оси 8 элементов – матриц 2×2, но мы хотим сделать четырехмерный
    массив, сохранив остальные три оси и их данные без изменений. Как раз это
    достаточно просто сделать с помощью функции expand_dims, следующим
    образом:

    x_test4 = np.expand_dims(x_test, axis=0)

    Обращаясь к
    свойству shape:

    x_test4.shape # (1, 8, 2, 2)

    Видим, что
    массив стал четырехмерным и первая добавленная ось axis0 содержит один
    элемент – трехмерный массив 8x2x2. При
    необходимости, мы всегда можем добавить новый элемент на эту ось:

    a = np.append(x_test4, x_test4, axis=0) # размерность (2, 8, 2, 2)

    или удалить
    ненужные элементы:

    b = np.delete(a, 0, axis=0) # размерность (1, 8, 2, 2)

    Здесь второй
    параметр 0 – индекс удаляемого элемента на оси axis0.

    Если нам нужно
    добавить последнюю ось в массиве, то для этого можно записать такую команду:

    b = np.expand_dims(x_test4, axis=-1) # размерность (1, 8, 2, 2, 1)

    Отрицательный
    индекс -1 – это следующая с конца ось. Если указать индекс -2, то добавится
    предпоследняя ось и так далее. Отрицательные индексы очень удобно использовать
    при работе с массивами произвольных размерностей.

    Следующая
    функция squeeze позволяет
    удалить все оси с одним элементом. Например, строчка:

    c = np.squeeze(b) # размерность (8, 2, 2)

    превращает
    массив размерностью (1, 8, 2, 2) в массив размерностью (8, 2, 2). При
    необходимости, дополнительно мы можем самостоятельно указать оси, которые
    следует удалять, например, так:

    c = np.squeeze(b, axis=0) # удалит только ось axis0, не затронув другие

    Но, если указать
    ось с числом элементов больше 1, то возникнет ошибка:

    c = np.squeeze(b, axis=1) # ошибка, на оси axis1 8 элементов

    Объект newaxis

    В NumPy добавлять новые
    оси иногда удобнее с помощью специального объекта np.newaxis. Например,
    пусть у нас есть одномерный массив:

    a = np.arange(1, 10) # array([1, 2, 3, 4, 5, 6, 7, 8, 9])

    У него одна ось
    – одно измерение. Добавим еще одну ось, допустим, в начало. С помощью объекта np.newaxis это можно
    сделать так:

    b = a[np.newaxis, :] # добавление оси axis0
    b.shape # (1, 9)

    Или, можно
    прописать сразу две оси:

    c = a[np.newaxis, :, np.newaxis]
    c.shape # (1, 9, 1)

    Как видите, это
    достаточно удобная операция.

    Видео по теме

    Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

    Переформатирование, изменение формы

    Python: Numpy-массивы

    Numpy

    Часто разработчикам приходится изменять размеры массивов. Например, переформатировать исходные данные, чтобы разделить их на подмассивы. В некоторых случаях требуется еще и объединять многомерные данные в единый массив значений. Чтобы решать такие задачи, массивы numpy.ndarray предоставляют набор методов, самым популярным из которых является метод reshape().

    В этом уроке разберем, как работать с размерами массивов numpy.ndarray и как получать их производные. Еще поговорим об ограничениях размерности и узнаем, как они помогают оптимизировать работу.

    Как изменить размер массива

    Представим, что нам нужно увеличить размер массива numpy.ndarray. Для этого будем идти по следующим шагам:

    1. Узнаем размер массива и индексы вдоль оси
    2. Изменим размер массива

    Рассмотрим каждый этап подробнее.

    Как узнать размер массива и индексы вдоль оси

    Чтобы изменить размер numpy.ndarray, нужно узнать его значение. Для этого используют атрибут shape:

    import numpy as np
    
    one_dimension_array = np.array(
        [0,1,2,3,4,5,6,7,8,9,10,11]
    )
    
    print(one_dimension_array.shape)
    # => (12,)
    
    two_dimensions_array = np.array(
        [
            [0,1,2],
            [3,4,5],
            [6,7,8],
            [9,10,11]
        ]
    )
    print(two_dimensions_array.shape)
    # => (4, 3)
    
    three_dimensions_array = np.array(
        [
            [
                [0,1],
                [2,3],
            ],
            [
                [4,5],
                [6,7],
            ],
            [
                [8,9],
                [10,11]
            ]
        ]
    )
    print(three_dimensions_array.shape)
    # => (3, 2, 2)
    

    В примере выше атрибут shape возвращает кортеж целых чисел. Длина кортежа указывает на размерность массива:

    • (12,) — одномерный массив
    • (4, 3) — двумерный массив
    • (3, 2, 2) — трехмерный массив

    Числа в кортеже означают количество элементов по конкретной оси индексов:

    • (12,) — 12 значений
    • (4, 3) — четыре блока значений по три значения в каждом
    • (3, 2, 2) — три блока значений, каждый из которых состоит из двух блоков по два значения

    Название ось индексов отсылает к декартовой системе координат. Вспомним ее основные правила:

    • Чтобы построить отрезок или другой одномерный объект, достаточно одной координатной оси
    • Чтобы построить квадрат или другой двумерный объект, необходима координатная плоскость из двух перпендикулярных осей
    • Чтобы построить куб или другой трехмерный объект, нужно три ортогональные оси координат

    Теперь, когда мы знаем размер исходного массива, можно изменять его форму. Для этого используем метод reshape().

    Как изменить размер массива с помощью метода reshape()

    В Python используется метод reshape(), с помощью которого можно получить двухмерный и трехмерный массив из одномерного. Этот обязательный параметр ожидает новый размер данных, к которому нужно переформатировать исходный массив.

    Попробуем получить двумерный массив two_dimensions_array из одномерного массива one_dimension_array. Для этого используем метод reshape() с новым размером данных (4, 3):

    print(one_dimension_array.reshape(((4, 3))))
    # => [[ 0  1  2]
    #  [ 3  4  5]
    #  [ 6  7  8]
    #  [ 9 10 11]]
    

    Чтобы получить трехмерный массив three_dimensions_array, достаточно также указать нужный размер:

    print(one_dimension_array.reshape((3, 2, 2)))
    # => [[[ 0  1]
    #   [ 2  3]]
    #  [[ 4  5]
    #   [ 6  7]]
    #  [[ 8  9]
    #   [10 11]]]
    

    Изменять форму массива можно не только от данных меньшей размерности к данным большей размерности. Это можно делать и в обратную сторону.

    Попробуем получить исходный одномерный массив one_dimension_array из двумерного массива two_dimensions_array:

    print(two_dimensions_array.reshape((12,)))
    # => [ 0  1  2  3  4  5  6  7  8  9 10 11]
    

    А тут переформатируем three_dimensions_array в two_dimensions_array:

    print(three_dimensions_array.reshape((4,3)))
    # => [[ 0  1  2]
    #  [ 3  4  5]
    #  [ 6  7  8]
    #  [ 9 10 11]]
    

    Необязательно уменьшать размер последовательно. Например, можно из трехмерного массива получить сразу одномерный:

    print(three_dimensions_array.reshape((12,)))
    # => [ 0  1  2  3  4  5  6  7  8  9 10 11]
    

    С помощью атрибута shape можно узнать размерность массива numpy.ndarray. А метод reshape поможет ее уменьшить или увеличить. Однако у этого массива есть ограничения по размеру данных — его нужно соблюдать, чтобы оптимизировать выполнения методов над массивами.

    Какие размеры массива допустимы

    У массива numpy.ndarray есть ограничения по размеру данных — по осям индексов должны быть данные одного размера. Это ограничение позволяет оптимизировать выполнения методов над массивами. Рассмотрим на примере.

    Допустим, нам нужно сконвертировать список из списков длиной три и два:

    np.array(
        [
            [0,1,2],
            [3,4,],
        ]
    )
    # => [list([0, 1, 2]) list([3, 4])]
    

    На первый взгляд у нас получился массив numpy.ndarray. Но если внимательно посмотреть на элементы, мы увидим, что получились списки, а не ожидаемые целочисленные массивы. Это ограничит дальнейшую работу с данными, потому что поведение многих методов меняется.

    Попробуем найти в данном массиве максимальный элемент 4. Это приведет к такому результату:

    print(np.array(
        [
            [0,1,2],
            [3,4,],
        ]
    ).max())
    # => [3, 4]
    

    В этом примере мы получили не тот результат, которого ожидали.

    Numpy старается предотвращать некорректные действия — для этого в нем есть система предупреждений и подсказок. Но это не значит, что не нужно следить за размером массива. Он играет важную роль в реализации методов библиотеки Numpy, поэтому рекомендуем обращать внимание на этот момент.

    В случае с методом reshape() Numpy вообще не дает совершить некорректную конвертацию массива из 12 элементов в массив из 15 элементов — три блока по пять значений. В этом случае он вызывает исключение:

    one_dimension_array.reshape(3,5)
    # => ValueError: cannot reshape array of size 12 into shape (3,5)
    

    Ограничения по размеру могут добавить неудобств, когда мы увеличиваем или уменьшаем размерность массива. При этом они позволяют не указывать некоторые значения размера, когда мы хотим его изменить.

    Как сделать автоматический расчет размера массива

    Ограничения на размер массива позволяют не указывать некоторые размеры в методе reshape(). Это можно оставить на автоматический расчет. Для этого нужное значение размерности поменяем на -1:

    print(one_dimension_array.reshape((4,3)))
    print(one_dimension_array.reshape(((4, -1))))
    print(one_dimension_array.reshape(((-1, 3))))
    # => [[ 0  1  2]
    #  [ 3  4  5]
    #  [ 6  7  8]
    #  [ 9 10 11]]
    

    Все преобразования в примере выше дают одинаковый результат. Необходимый размер рассчитывается автоматически, исходя из количества элементов.

    Для массивов большей размерности это работает по такому же принципу:

    print(one_dimension_array.reshape((3, 2, 2)))
    print(one_dimension_array.reshape((-1, 2, 2)))
    print(one_dimension_array.reshape((3, -1, 2)))
    print(one_dimension_array.reshape((3, 2, -1)))
    # => [[[ 0  1]
    #   [ 2  3]]
    #  [[ 4  5]
    #   [ 6  7]]
    #  [[ 8  9]
    #   [10 11]]]
    

    Чтобы получить одномерный массив и использовать автоматический расчет, не нужно находить количество элементов. Строки в примере ниже дают одинаковый результат:

    print(three_dimensions_array.reshape((12,)))
    print(three_dimensions_array.reshape((-1,)))
    # => [ 0  1  2  3  4  5  6  7  8  9 10 11]
    

    Теперь вы знаете, как определять размерность массива. Вы умеете изменять размер и рассчитывать его автоматически. Чтобы закрепить знания на практике, рассмотрим еще один пример.

    Как размер массива меняется на практике

    Изменение формы массива помогает подготовить исходные данные — после такой обработки их будет удобнее анализировать и преобразовывать.

    Представим сервис платформы продаж, который логирует данные по сетевым магазинам в конце рабочего дня в определенном порядке. Аналитики выгрузили данные из закрытого контура платформы. Так они получили 24 значения недельных продаж сети:

    orders = [7, 1, 7, 8, 4, 2, 4, 5, 3, 5, 2, 3, 8, 12, 8, 7, 15, 11, 13, 9, 21, 18, 17, 21, 25, 16, 25, 17,]
    shops_number = 4
    
    orders_matrix = np.array(orders)
    orders_matrix = orders_matrix.reshape(-1, shops_number)
    print(orders_matrix)
    # => [[ 7  1  7  8]
    #  [ 4  2  4  5]
    #  [ 3  5  2  3]
    #  [ 8 12  8  7]
    #  [15 11 13  9]
    #  [21 18 17 21]
    #  [25 16 25 17]]
    
    print(orders_matrix.shape)
    # => (7, 4)
    

    Полученный массив данных можно визуализировать в виде такой таблицы:

    День Магазин №1 Магазин №2 Магазин №3 Магазин №4
    0 7 1 7 8
    1 4 2 4 5
    2 3 5 2 3
    3 8 12 8 7
    4 15 11 13 9
    5 21 18 17 21
    6 25 16 25 17

    Выводы

    Метод shape — важный атрибут для структурного описания массива numpy.ndarray. Он помогает узнать размер вдоль каждой оси.

    Трудность NumPy в том, что операции над многомерными массивами бывает сложно представить. Хаус Лин подготовил шпаргалки, которые сделают преобразование массивов нагляднее. Руководство подойдёт и для знакомства с NumPy.

    Аналог range для массивов. Чтобы создать простой массив, используем функцию np.arange(). Удобно взять небольшое составное число, например, 12.

            import numpy as np
    
    a1 = np.arange(1, 13)  # числа от 1 до 12
    
    print(a1.shape)
    > (12,)
    
    print(a1)
    > [ 1  2  3  4  5  6  7  8  9 10 11 12]
        

    Создан одномерный массив из 12 чисел.

    Создан одномерный массив из 12 чисел.

    2. Изменяем форму с помощью метода reshape()

    Оси и измерения. Чтобы изменить форму массива a1 , используем метод reshape(). Преобразуем одномерный массив из 12 чисел в двумерную таблицу размером 3×4. Первое число – количество строк, второе – столбцов. Строки соответствуют оси (англ. axis) 0, столбцы – оси 1. Ещё их называют измерениями (англ. dimensions).

            a1_2d = a1.reshape(3, 4)
    
    print(a1_2d.shape)
    > (3, 4)
    
    print(a1_2d)
    > [[ 1  2  3  4]
       [ 5  6  7  8]
       [ 9 10 11 12]]
        

    Иллюстрированное руководство по изменению формы массивов NumPy

    Автоматическое вычисление размерности. Если нужно, чтобы NumPy сам определил размер незаданного измерения, передайте на этой позиции значение -1:

            a1.reshape(3, 4)
    a1.reshape(-1, 4)  # то же самое, что a1.reshape(3, 4)
    
    a1.reshape(3, 4)
    a1.reshape(3, -1)  # то же самое, что a1.reshape(3, 4)
    
    a1.reshape(2, 6)
    a1.reshape(2, -1)  # то же самое, что a1.reshape(2, 6)
        

    3. Изменяем форму по разным направлениям

    Порядок переноса С. По умолчанию reshape() перестраивает исходный массив по оси 0. То есть в нашем примере отдельные числа из одномерного массива «переносятся» в двумерный построчно. Поведение можно изменить, передав значение параметру order. Дефолтный метод похож на то, как преобразование реализовано в C. Параметр order по умолчанию имеет значение 'C':

            a1.reshape(3, 4)
    a1.reshape(3, 4, order='C') # даст идентичный результат
    
        

    Порядок переноса Fortran. Если вы привыкли к тому, как преобразуются массивы в MATLAB, то это делается так же, как в Fortran. Поэтому используйте значение 'F':

            a1.reshape(3, 4, order='F')  # столбец за столбцом
    > [[ 1  4  7 10]
       [ 2  5  8 11]
       [ 3  6  9 12]]
        

    Иллюстрированное руководство по изменению формы массивов NumPy

    Какую размерность имеет исходный массив a1? Может показаться, что массив a1 имеет размерность (1, 12). Но это одномерный массив с размерностью(12, ). Чтобы преобразовать одномерный массив к двумерному, используем метод reshape():

            print(a1)  # какая форма?
    > [ 1  2  3  4  5  6  7  8  9 10 11 12]
    
    print(a1.shape)
    > (12,)
    
    a1_1_by_12 = a1.reshape(1, -1)  # преобразуем к 1x12
    
    print(a1_1_by_12)  # обратите внимание на двойные скобки
    > [[ 1  2  3  4  5  6  7  8  9 10 11 12]]
    
    print(a1_1_by_12.shape)  # двумерный массив
    > (1, 12)
        

    4. Схлопываем массив до одномерного

    Из 2D в 1D. Метод ravel() преобразует многомерные массивы в одномерные. Тот же параметр order определяет, «схлопнется» ли массив построчно или столбец за столбцом:

            print(a1_2d)
    > [[ 1  2  3  4]
       [ 5  6  7  8]
       [ 9 10 11 12]]
    
    print(a1_2d.ravel())  # строка за строкой
    > [ 1  2  3  4  5  6  7  8  9 10 11 12]
    
    print(a1_2d.ravel(order='F'))  # столбец за столбцом
    > [ 1  5  9  2  6 10  3  7 11  4  8 12]
        

    5. Повышаем размерность, сшивая массивы друг с другом

    Иллюстрированное руководство по изменению формы массивов NumPy

    Создадим два массива:

            a1 = np.arange(1, 13)
    print(a1)
    > [ 1  2  3  4  5  6  7  8  9 10 11 12]
    
    a2 = np.arange(13, 25)
    print(a2)
    > [13 14 15 16 17 18 19 20 21 22 23 24]
        

    Чтобы соединить два одномерных масива в двумерный, используем метод np.stack(). Параметр axis указывает индекс оси в результирующем массиве, по которой соединяются входные. По умолчанию axis = 0, и массивы стыкуются строка к строке:

            stack0 = np.stack((a1, a1, a2, a2))
    print(stack0.shape)
    > (4, 12)
    
    print(stack0)
    > [[ 1  2  3  4  5  6  7  8  9 10 11 12]
       [ 1  2  3  4  5  6  7  8  9 10 11 12]
       [13 14 15 16 17 18 19 20 21 22 23 24]
       [13 14 15 16 17 18 19 20 21 22 23 24]]
        

    Чтобы соединить массивы столбец к столбцу, явным образом передаем axis = 1:

            stack1 = np.stack((a1, a1, a2, a2), axis=1)
    print(stack1.shape)
    > (12, 4)
    print(stack1)
    > [[ 1  1 13 13]
       [ 2  2 14 14]
       [ 3  3 15 15]
       [ 4  4 16 16]
       [ 5  5 17 17]
       [ 6  6 18 18]
       [ 7  7 19 19]
       [ 8  8 20 20]
       [ 9  9 21 21]
       [10 10 22 22]
       [11 11 23 23]
       [12 12 24 24]]
        

    Как не повышать число измерений? Функция hstack() соединяет массивы горизонтально без изменения размерности. Если применить ее к одномерным массивам, получится длинный одномерный массив:

            stack_long = np.hstack((a1, a2))
    
    print(stack_long.shape)
    > (24,)
    
    print(stack_long)
    > [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
        

    6. Создаем трехмерный массив

    Где применяются многомерные массивы? Массивы, живущие в трёх и более измерениях, активно используются в глубоком обучении. Например, для операций с изображениями. В работе с нейросетями преобразование многомерных массивов – обычное дело.

    Для начала создадим два двумерных массива размером 3×4:

            a1 = np.arange(1, 13).reshape(3, -1)
    a2 = np.arange(13, 25).reshape(3, -1)
    
    print(a1)
    > [[ 1  2  3  4]
       [ 5  6  7  8]
       [ 9 10 11 12]]
    
    print(a2)
    > [[13 14 15 16]
       [17 18 19 20]
       [21 22 23 24]]
        

    Иллюстрированное руководство по изменению формы массивов NumPy

    Теперь соберём из них трёхмерный массив:

            a3_0 = np.stack((a1, a2))  # дефолтное axis=0, одна плоскость ложится на другую
    a3_1 = np.stack((a1, a2), axis=1)
    a3_2 = np.stack((a1, a2), axis=2)
    
    print(a3_0.shape)
    > (2, 3, 4)
    
    print(a3_1.shape)
    > (3, 2, 4)
    
    print(a3_2.shape)
    > (3, 4, 2)
        

    Иллюстрированное руководство по изменению формы массивов NumPy

    Как выглядят массивы:

            print(a3_0)
    > [[[ 1  2  3  4]
        [ 5  6  7  8]
        [ 9 10 11 12]]
    
       [[13 14 15 16]
        [17 18 19 20]
        [21 22 23 24]]]
    
    print(a3_1)
    > [[[ 1  2  3  4]
        [13 14 15 16]]
    
       [[ 5  6  7  8]
        [17 18 19 20]]
    
       [[ 9 10 11 12]
        [21 22 23 24]]]
    
    print(a3_2)
    > [[[ 1 13]
        [ 2 14]
        [ 3 15]
        [ 4 16]]
    
       [[ 5 17]
        [ 6 18]
        [ 7 19]
        [ 8 20]]
    
       [[ 9 21]
        [10 22]
        [11 23]
        [12 24]]]
        

    Чтобы извлечь плоскость массива a1 из трехмерного, нужно передать 0 по соответствующему индексу оси:

            print(a1)
    > [[ 1  2  3  4]
       [ 5  6  7  8]
       [ 9 10 11 12]]
    
    a3_0[0, :, :]
    a3_1[:, 0, :]
    a3_2[:, :, 0]
        

    Чтобы то же самое сделать для двумерного массива a2, на тех же позициях вместо 0 отправляем индекс 1. Символы двоеточия указывают, что нужно взять все элементы соответствующей оси.

    7. Схлопываем многомерные массивы

    Метод ravel() действует и для массивов с числом размерностей больше 2:

    Иллюстрированное руководство по изменению формы массивов NumPy

            print(a3_0)
    > [[[ 1  2  3  4]
        [ 5  6  7  8]
        [ 9 10 11 12]]
    
       [[13 14 15 16]
        [17 18 19 20]
        [21 22 23 24]]]
    
    print(a3_0.ravel())
    > [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
    
    print(a3_0.ravel(order='F'))
    > [ 1 13  5 17  9 21  2 14  6 18 10 22  3 15  7 19 11 23  4 16  8 20 12 24]
        

    8. Изменяем форму многомерных массивов

    Метод reshape() также работает с массивами любой размерности. Главное условие, которое нужно соблюдать – количество элементов в массиве не должно меняться:

            print(a3_0)  # исходный размер 2x3x4
    > [[[ 1  2  3  4]
        [ 5  6  7  8]
        [ 9 10 11 12]]
    
       [[13 14 15 16]
        [17 18 19 20]
        [21 22 23 24]]]
    
    print(a3_0.reshape(4, -1))  # преобразуем к 4x6
    > [[ 1  2  3  4  5  6]
       [ 7  8  9 10 11 12]
       [13 14 15 16 17 18]
       [19 20 21 22 23 24]]
    
    print(a3_0.reshape(4, -1, order='F'))  # делаем то же самое, но в F-стиле
    > [[ 1  9  6  3 11  8]
       [13 21 18 15 23 20]
       [ 5  2 10  7  4 12]
       [17 14 22 19 16 24]]
    
    print(a3_0.reshape(4, 2, 3))  # преобразуем к трехмерному массиву другой формы
    > [[[ 1  2  3]
        [ 4  5  6]]
       [[ 7  8  9]
        [10 11 12]]
       [[13 14 15]
        [16 17 18]]
       [[19 20 21]
        [22 23 24]]]
        

    Заключение

    Напоследок приведем изображение со всеми элементами рассказа вместе (оригинальный pdf). Напишите нам в комментариях, если что-то осталось непонятным и требует пояснений.

    Иллюстрированное руководство по изменению формы массивов NumPy

    Изменение формы и размера массива на месте.

    Parameters
    new_shape кортеж целых чисел или n целых чисел

    Форма измененного массива.

    refcheckbool, optional

    Если Фальшивка,подсчет ссылок не будет проверен.По умолчанию-Истина.

    Returns
    None
    Raises
    ValueError

    Если a не владеет своими собственными данными, либо существуют ссылки или представления на него, необходимо изменить память данных. Только PyPy: всегда будет увеличиваться, если необходимо изменить память данных, поскольку нет надежного способа определить, существуют ли ссылки или представления на нее.

    SystemError

    Если указан аргумент ключевого слова order . Такое поведение является ошибкой в ​​NumPy.

    See also

    resize

    Возвращает новый массив с заданной формой.

    Notes

    При необходимости это перераспределяет пространство для области данных.

    Изменять размер можно только смежные массивы (последовательные в памяти элементы данных).

    Цель проверки счетчика ссылок — убедиться, что вы не используете этот массив в качестве буфера для другого объекта Python, а затем перераспределите память. Однако счетчик ссылок может увеличиваться и другими способами, поэтому, если вы уверены, что не разделили память для этого массива с другим объектом Python, вы можете безопасно установить refcheck на False.

    Examples

    Уменьшение массива:массив сглаживается (в порядке хранения данных в памяти),изменяется размер и форма:

    >>> a = np.array([[0, 1], [2, 3]], order='C')
    >>> a.resize((2, 1))
    >>> a
    array([[0],
           [1]])
    
    >>> a = np.array([[0, 1], [2, 3]], order='F')
    >>> a.resize((2, 1))
    >>> a
    array([[0],
           [2]])
    

    Расширение массива:как указано выше,но отсутствующие записи заполняются нулями:

    >>> b = np.array([[0, 1], [2, 3]])
    >>> b.resize(2, 3) 
    >>> b
    array([[0, 1, 2],
           [3, 0, 0]])
    

    Ссылка на массив предотвращает изменение размера…

    >>> c = a
    >>> a.resize((1, 1))
    Traceback (most recent call last):
    ...
    ValueError: cannot resize an array that references or is referenced ...
    

    Если refcheck не ложна :

    >>> a.resize((1, 1), refcheck=False)
    >>> a
    array([[0]])
    >>> c
    array([[0]])
    

    Понравилась статья? Поделить с друзьями:

    Читайте также:

  • Как изменить размер ярлыков на рабочем столе ноутбука
  • Как изменить размер ярлыков на рабочем столе вин 10
  • Как изменить размер ярлыков на рабочем столе андроид
  • Как изменить размер ярлыков на раб столе
  • Как изменить размер ярлыков на панели задач windows 10

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии