NumPy: операции с многомерными массивами ndarray

Python

Введение

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

В этой статье будут представлены некоторые основные общие операции ndarray, которые вы можете использовать при анализе данных.

создать ндаррай

Есть много способов создать ndarray, мы можем использовать np.random для случайной генерации данных:

import numpy as np
# Generate some random data
data = np.random.randn(2, 3)
data
array([[ 0.0929,  0.2817,  0.769 ],
       [ 1.2464,  1.0072, -1.2962]])

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

data1 = [6, 7.5, 8, 0, 1]
arr1 = np.array(data1)
array([6. , 7.5, 8. , 0. , 1. ])

Создайте многомерный массив из списка:

data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data2)
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])

Используйте np.zeros для создания массива с начальным значением 0:

np.zeros(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

Создайте двумерный массив:

np.zeros((3, 6))
array([[0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.]])

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

np.empty((2, 3, 2))
array([[[0., 0.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [0., 0.]]])

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

Используйте arange для создания массива классов диапазонов:

np.arange(15)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

Укажите dtype элементов в массиве:

arr1 = np.array([1, 2, 3], dtype=np.float64)
arr2 = np.array([1, 2, 3], dtype=np.int32)

свойства ndarray

Форму массива можно получить через data.shape.

data.shape
(2, 3)

Получить информацию об измерении через ndim:

arr2.ndim
2

Конкретный тип данных можно получить через data.dtype.

data.dtype
dtype('float64')

Преобразование типов элементов в ndarray

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

arr = np.array([1, 2, 3, 4, 5])
arr.dtype
dtype('int64')

float_arr = arr.astype(np.float64)
float_arr.dtype
dtype('float64')

Выше мы использовали astype для преобразования ndarray типа int64 в тип float64.

Усечение происходит автоматически, если диапазон преобразованного типа не совпадает:

arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
arr.astype(np.int32)

array([ 3, -1, -2,  0, 12, 10], dtype=int32)

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

Математические операции над ndarray

Массивы могут работать как с константами, так и с массивами:

arr = np.array([[1., 2., 3.], [4., 5., 6.]])

arr * arr

array([[ 1.,  4.,  9.],
       [16., 25., 36.]])

arr + 10

array([[11., 12., 13.],
       [14., 15., 16.]])

arr - arr

array([[0., 0., 0.],
       [0., 0., 0.]])

1 / arr

array([[1.    , 0.5   , 0.3333],
       [0.25  , 0.2   , 0.1667]])

arr ** 0.5

array([[1.    , 1.4142, 1.7321],
       [2.    , 2.2361, 2.4495]])

Массивы также можно сравнивать, сравнивая размер каждого элемента в массиве:

arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])

arr2 > arr

array([[False,  True, False],
       [ True, False,  True]])

индекс и срез

основное использование

Давайте сначала рассмотрим основное использование индекса и среза.Индекс в основном используется так же, как и обычные массивы, которые используются для доступа к элементу в массиве.

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

# 构建一维数组
arr = np.arange(10)

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

# index访问
arr[5]
5

# 切片访问
arr[5:8]
array([5, 6, 7])

# 切片修改
arr[5:8] = 12
array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])

# 切片可以修改原数组的值
arr_slice = arr[5:8]
arr_slice[1] = 12345
arr

array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
           9])

# 构建二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]

array([7, 8, 9])

# index 二维数组
arr2d[0][2]
3

# index二维数组
arr2d[0, 2]
3

# 构建三维数组
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d

array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

# index三维数组
arr3d[0]

array([[1, 2, 3],
       [4, 5, 6]])

# copy是硬拷贝,和原数组的值相互不影响
old_values = arr3d[0].copy()
arr3d[0] = 42

arr3d

array([[[42, 42, 42],
        [42, 42, 42]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

arr3d[0] = old_values
arr3d

array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

# index 三维数组
arr3d[1, 0]

array([7, 8, 9])

x = arr3d[1]
x

array([[ 7,  8,  9],
       [10, 11, 12]])

x[0]

array([7, 8, 9])

index with slice

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

Срез, представленный в виде индекса, может принимать различные формы.

У него есть голова и хвост, указывающие на то, что индекс начинается с 1 и заканчивается на 6-1:

arr[1:6]
array([ 1,  2,  3,  4, 64])

Нет головы и хвоста, что указывает на то, что индекс начинается с 0 и заканчивается на -1 в конце:

arr2d[:2]
array([[1, 2, 3],
       [4, 5, 6]])

С головой и хвостом это означает, начиная с начала и заканчивая всеми данными:

arr2d[:2, 1:]
array([[2, 3],
       [5, 6]])
arr2d[1, :2]
array([4, 5])

boolean index

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

Давайте сначала посмотрим, как построить массив логического типа:

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
names == 'Bob'

array([ True, False, False,  True, False, False, False])

Выше мы вернули массив, содержащий только True и False для сравнения.

Этот массив можно использовать как значение индекса для доступа к массиву:

#  构建一个7 * 4 的数组
data = np.random.randn(7, 4)

array([[ 0.275 ,  0.2289,  1.3529,  0.8864],
       [-2.0016, -0.3718,  1.669 , -0.4386],
       [-0.5397,  0.477 ,  3.2489, -1.0212],
       [-0.5771,  0.1241,  0.3026,  0.5238],
       [ 0.0009,  1.3438, -0.7135, -0.8312],
       [-2.3702, -1.8608, -0.8608,  0.5601],
       [-1.2659,  0.1198, -1.0635,  0.3329]])

# 通过boolean数组来访问:
data[names == 'Bob']
array([[ 0.275 ,  0.2289,  1.3529,  0.8864],
       [-0.5771,  0.1241,  0.3026,  0.5238]])

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

data[names == 'Bob', 3]
array([0.8864, 0.5238])

Можно использовать~знак отрицания:

data[~(names == 'Bob')]
array([[-2.0016, -0.3718,  1.669 , -0.4386],
       [-0.5397,  0.477 ,  3.2489, -1.0212],
       [ 0.0009,  1.3438, -0.7135, -0.8312],
       [-2.3702, -1.8608, -0.8608,  0.5601],
       [-1.2659,  0.1198, -1.0635,  0.3329]])

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

data[data < 0] = 0
array([[0.275 , 0.2289, 1.3529, 0.8864],
       [0.    , 0.    , 1.669 , 0.    ],
       [0.    , 0.477 , 3.2489, 0.    ],
       [0.    , 0.1241, 0.3026, 0.5238],
       [0.0009, 1.3438, 0.    , 0.    ],
       [0.    , 0.    , 0.    , 0.5601],
       [0.    , 0.1198, 0.    , 0.3329]])

data[names != 'Joe'] = 7
array([[7.    , 7.    , 7.    , 7.    ],
       [0.    , 0.    , 1.669 , 0.    ],
       [7.    , 7.    , 7.    , 7.    ],
       [7.    , 7.    , 7.    , 7.    ],
       [7.    , 7.    , 7.    , 7.    ],
       [0.    , 0.    , 0.    , 0.5601],
       [0.    , 0.1198, 0.    , 0.3329]])

Fancy indexing

Причудливое индексирование, также известное как причудливое индексирование, относится к использованию массива целых чисел для индексации.

Например, сначала создадим массив 8*4:

arr = np.empty((8, 4))
for i in range(8):
    arr[i] = i
arr
array([[0., 0., 0., 0.],
       [1., 1., 1., 1.],
       [2., 2., 2., 2.],
       [3., 3., 3., 3.],
       [4., 4., 4., 4.],
       [5., 5., 5., 5.],
       [6., 6., 6., 6.],
       [7., 7., 7., 7.]])

Затем, используя массив целых чисел для индексации, строки будут выбраны в указанном порядке:

arr[[4, 3, 0, 6]]
array([[4., 4., 4., 4.],
       [3., 3., 3., 3.],
       [0., 0., 0., 0.],
       [6., 6., 6., 6.]])

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

arr[[-3, -5, -7]]
array([[5., 5., 5., 5.],
       [3., 3., 3., 3.],
       [1., 1., 1., 1.]])

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

arr = np.arange(32).reshape((8, 4))
arr
array([[ 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, 25, 26, 27],
       [28, 29, 30, 31]])

Выше мы построили массив 8*4.

arr[[1, 5, 7, 2], [0, 3, 1, 2]]
array([ 4, 23, 29, 10])

Затем возьмите их первое значение в столбце 2, третье значение в столбце 6 и так далее. Наконец, получите одномерный массив.

преобразование массива

Мы можем преобразовывать массивы разных размеров, а также преобразовывать оси массивов.

Метод reshape может преобразовать массив в любую форму:

arr = np.arange(15).reshape((3, 5))
arr
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

Массивы также предоставляют команду T, которая меняет оси массива на противоположные:

arr.T
array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])

Для многомерных массивов вы можете использовать транспонирование для транспонирования осей:

arr = np.arange(16).reshape((2, 2, 4))
arr
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
        
arr.transpose((1, 0, 2))
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

Как понять приведенное выше транспонирование ((1, 0, 2))?

Его смысл в том, чтобы поменять местами оси x и y и оставить ось z неизменной.

Выше мы создали трехмерный массив с тремя осями, используя метод reshape((2, 2, 4)) . Его форма 2 * 2 * 4.

Сначала посмотрите на соответствующие отношения:

(0, 0) -> [ 0, 1, 2, 3]

(0, 1) -> [4, 5, 6, 7]

(1, 0) -> [8, 9, 10, 11]

(1, 1) -> [12, 13, 14, 15]

После преобразования:

(0, 0) -> [ 0, 1, 2, 3]

(0, 1) -> [8, 9, 10, 11]

(1, 0) - "[4, 5, 6, 7]

(1, 1) -> [12, 13, 14, 15]

Таким образом, мы получаем результат выше.

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

Вы также можете использовать swapaxes, чтобы поменять местами две оси, приведенный выше пример можно переписать как:

arr.swapaxes(0,1)

Эта статья была включена вwoohoo.floydpress.com/09-python-вы…

Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!

Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!