Spec-Zone.ru › NumPy 1.20

NumPy для пользователей MATLAB

Введение

MATLAB® и NumPy имеют много общего, но NumPy был создан для работы с Python, а не для того, чтобы быть клоном MATLAB. Это руководство поможет пользователям MATLAB начать работу с NumPy.

Некоторые ключевые различия

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

В NumPy базовый тип — многомерный array. Присваивания массивов в NumPy обычно хранятся как n-мерные массивы с минимальным типом, необходимым для хранения объектов в последовательности, если вы не укажете количество измерений и тип. NumPy выполняет операции по элементам, поэтому умножение двумерных массивов на * не является матричным умножением — это умножение по элементам. (Оператор @, доступный с Python 3.5, может использоваться для обычного матричного умножения.)

В MATLAB индексы нумеруются с 1; a(1) — первый элемент. См. примечание ИНДЕКСОВАНИЕ

NumPy, как и Python, нумерует индексы с 0; a[0] — первый элемент.

Язык сценариев MATLAB был создан для линейной алгебры, поэтому синтаксис некоторых манипуляций с массивами более компактен, чем в NumPy. С другой стороны, API для добавления графических интерфейсов пользователя и создания полноценных приложений — скорее, дополнительный элемент.

NumPy основан на Python, языке общего назначения. Преимущество NumPy — доступ к библиотекам Python, включая: SciPy, Matplotlib, Pandas, OpenCV и многое другое. Кроме того, Python часто встраивается как язык сценариев в другое программное обеспечение, что позволяет использовать NumPy и там.

Фрагментирование массивов MATLAB использует семантику передачи по значению с ленивой копией-при записи, чтобы предотвратить создание копий до тех пор, пока они не понадобятся. Операции фрагментирования копируют части массива.

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

Приблизительные эквиваленты

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

В таблице ниже предполагается, что вы выполнили следующие команды в Python:

import numpy as np
from scipy import io, integrate, linalg, signal
from scipy.sparse.linalg import eigs

Также предполагается ниже, что если в Примечаниях упоминается «матрица», то аргументы — двумерные сущности.

Эквиваленты общего назначения

MATLAB

NumPy

Примечания

help func

info(func) или help(func) или func? (в IPython)

получить справку по функции func

which func

см. примечание СПРАВКА

узнать, где определена func

type func

np.source(func) или func?? (в IPython)

распечатать исходный код func (если это не встроенная функция)

% comment

# comment

комментировать строку кода текстом comment

for i=1:3
    fprintf('%i\n',i)
end
for i in range(1, 4):
   print(i)

использовать цикл for для печати чисел 1, 2 и 3, используя range

a && b

a and b

короткое логическое И (оператор &&); только скалярные аргументы (родной оператор Python)

a || b

a or b

короткое логическое ИЛИ (оператор ||); только скалярные аргументы (родной оператор Python)

>> 4 == 4
ans = 1
>> 4 == 5
ans = 0
>>> 4 == 4
True
>>> 4 == 5
False

Объекты булевых значений в Python — это True и False, в отличие от логических типов MATLAB 1 и 0.

a=4
if a==4
    fprintf('a = 4\n')
elseif a==5
    fprintf('a = 5\n')
end
a = 4
if a == 4:
    print('a = 4')
elif a == 5:
    print('a = 5')

создать оператор if-else для проверки, равно ли a 4 или 5, и вывести результат

1*i, 1*j, 1i, 1j

1j

комплексные числа

eps

np.finfo(float).eps или np.spacing(1)

Верхняя граница относительной погрешности из-за округления в 64-битном формате с плавающей точкой.

load data.mat

io.loadmat('data.mat')

Загрузка переменных MATLAB, сохраненных в файле data.mat. (Примечание: при сохранении массивов в data.mat в MATLAB/Octave используйте современный двоичный формат. scipy.io.loadmat создаст словарь сохраненных массивов и дополнительной информацией.)

ode45

integrate.solve_ivp(f)

интегрирование ОДУ методом Рунге-Кутты 4,5

ode15s

integrate.solve_ivp(f, method='BDF')

интегрирование ОДУ методом BDF

Эквиваленты линейной алгебры

MATLAB

NumPy

Заметки

ndims(a)

np.ndim(a) или a.ndim

число измерений массива a

numel(a)

np.size(a) или a.size

количество элементов массива a

size(a)

np.shape(a) или a.shape

«размер» массива a

size(a,n)

a.shape[n-1]

получение числа элементов n-го измерения массива a. (Обратите внимание, что MATLAB использует индексацию с 1, а Python — с 0. См. заметку ИНДЕКСИРОВАНИЕ)

[ 1 2 3; 4 5 6 ]

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

определение двумерного массива 2x3

[ a b; c d ]

np.block([[a, b], [c, d]])

создание матрицы из блоков a, b, c, и d

a(end)

a[-1]

доступ к последнему элементу в векторе MATLAB (1xn или nx1) или одномерном массиве NumPy a (длина n)

a(2,5)

a[1, 4]

доступ к элементу во второй строке, пятом столбце двумерного массива a

a(2,:)

a[1] или a[1, :]

вся вторая строка двумерного массива a

a(1:5,:)

a[0:5] или a[:5] или a[0:5, :]

первые 5 строк двумерного массива a

a(end-4:end,:)

a[-5:]

последние 5 строк двумерного массива a

a(1:3,5:9)

a[0:3, 4:9]

Первые три строки и пятый по девятый столбцы двумерного массива, a.

a([2,4,5],[1,3])

a[np.ix_([1, 3, 4], [0, 2])]

строки 2, 4 и 5 и столбцы 1 и 3. Это позволяет изменить матрицу, и не требует обычного среза.

a(3:2:21,:)

a[2:21:2,:]

каждая вторая строка a, начиная с третьей и заканчивая двадцать первой

a(1:2:end,:)

a[ ::2,:]

каждая вторая строка a, начиная с первой

a(end:-1:1,:) или flipud(a)

a[::-1,:]

a со строками в обратном порядке

a([1:end 1],:)

a[np.r_[:len(a),0]]

a с копией первой строки, добавленной в конец

a.'

a.transpose() или a.T

транспонирование a

a'

a.conj().transpose() или a.conj().T

сопряженное транспонирование a

a * b

a @ b

умножение матриц

a .* b

a * b

умножение по элементам

a./b

a/b

деление по элементам

a.^3

a**3

возведение в степень по элементам

(a > 0.5)

(a > 0.5)

матрица, i,j-й элемент которой равен (a_ij > 0.5). Результат MATLAB — массив логических значений 0 и 1. Результат NumPy — массив с логическими значениями False и True.

find(a > 0.5)

np.nonzero(a > 0.5)

найти индексы, где (a > 0.5)

a(:,find(v > 0.5))

a[:,np.nonzero(v > 0.5)[0]]

извлечь столбцы a где вектор v > 0.5

a(:,find(v>0.5))

a[:, v.T > 0.5]

извлечь столбцы a где столбец-вектор v > 0.5

a(a<0.5)=0

a[a < 0.5]=0

a с элементами, меньшими 0.5, обнулёнными

a .* (a>0.5)

a * (a > 0.5)

a с элементами, меньшими 0.5, обнулёнными

a(:) = 3

a[:] = 3

установить все значения на одно и то же скалярное значение

y=x

y = x.copy()

NumPy присваивает по ссылке

y=x(2,:)

y = x[1, :].copy()

Срезы NumPy по ссылке

y=x(:)

y = x.flatten()

преобразование массива в вектор (обратите внимание, что это приводит к созданию копии). Чтобы получить тот же порядок данных, что и в MATLAB, используйте x.flatten('F').

1:10

np.arange(1., 11.) или np.r_[1.:11.] или np.r_[1:10:10j]

создание возрастающего вектора (см. заметку ДИАПАЗОНЫ)

0:9

np.arange(10.) или np.r_[:10.] или np.r_[:9:10j]

создание возрастающего вектора (см. заметку ДИАПАЗОНЫ)

[1:10]'

np.arange(1.,11.)[:, np.newaxis]

создание столбца-вектора

zeros(3,4)

np.zeros((3, 4))

двумерный массив 3x4, заполненный 64-битными плавающими нулями

zeros(3,4,5)

np.zeros((3, 4, 5))

трёхмерный массив 3x4x5, заполненный 64-битными плавающими нулями

ones(3,4)

np.ones((3, 4))

двумерный массив 3x4, заполненный 64-битными плавающими единицами

eye(3)

np.eye(3)

единичная матрица 3x3

diag(a)

np.diag(a)

возвращает вектор диагональных элементов двумерного массива a

diag(v,0)

np.diag(v, 0)

возвращает квадратную диагональную матрицу, ненулевые значения которой — элементы вектора v

rng(42,'twister')
rand(3,4)
from numpy.random import default_rng
rng = default_rng(42)
rng.random(3, 4)

или более старая версия: random.rand((3, 4))

генерация случайного массива 3x4 с генератором случайных чисел по умолчанию и seed = 42

linspace(1,3,4)

np.linspace(1,3,4)

4 равномерно распределённых образца между 1 и 3 включительно

[x,y]=meshgrid(0:8,0:5)

np.mgrid[0:9.,0:6.] или np.meshgrid(r_[0:9.],r_[0:6.]

два двумерных массива: один с x-значениями, другой с y-значениями

ogrid[0:9.,0:6.] или np.ix_(np.r_[0:9.],np.r_[0:6.]

лучший способ вычисления функций на сетке

[x,y]=meshgrid([1,2,4],[2,4,5])

np.meshgrid([1,2,4],[2,4,5])

ix_([1,2,4],[2,4,5])

лучший способ вычисления функций на сетке

repmat(a, m, n)

np.tile(a, (m, n))

создание m × n копий a

[a b]

np.concatenate((a,b),1) или np.hstack((a,b)) или np.column_stack((a,b)) или np.c_[a,b]

конкатенация столбцов a и b

[a; b]

np.concatenate((a,b)) или np.vstack((a,b)) или np.r_[a,b]

конкатенация строк a и b

max(max(a))

a.max() или np.nanmax(a)

максимальный элемент a (с ndims(a) ≤ 2 для MATLAB, если есть NaN, nanmax проигнорирует их и вернёт наибольшее значение)

max(a)

a.max(0)

максимальный элемент каждого столбца массива a

max(a,[],2)

a.max(1)

максимальный элемент каждой строки массива a

max(a,b)

np.maximum(a, b)

сравнивает a и b поэлементно и возвращает максимальное значение из каждой пары

norm(v)

np.sqrt(v @ v) или np.linalg.norm(v)

норма L2 вектора v

a & b

logical_and(a,b)

поэлементный оператор AND (ufunc NumPy) См. заметку LOGICOPS

a | b

np.logical_or(a,b)

поэлементный оператор OR (ufunc NumPy) См. заметку LOGICOPS

bitand(a,b)

a & b

битовый оператор AND (родной для Python и ufunc NumPy)

bitor(a,b)

a | b

побитовое ИЛИ (Python и NumPy ufunc)

inv(a)

linalg.inv(a)

обратная матрица квадратной 2D-матрицы a

pinv(a)

linalg.pinv(a)

псевдообратная матрица 2D-матрицы a

rank(a)

linalg.matrix_rank(a)

ранг матрицы 2D-матрицы a

a\b

a квадратная; linalg.lstsq(a, b) в противном случае

решение уравнения a x = b для x

b/a

Решить a.T x.T = b.T вместо этого

решение уравнения x a = b для x

[U,S,V]=svd(a)

U, S, Vh = linalg.svd(a), V = Vh.T

разложение по сингулярным значениям a

c=chol(a) где a==c'*c

c = linalg.cholesky(a) где a == c@c.T

разложение Холецкого 2D-матрицы (chol(a) в MATLAB возвращает верхнюю треугольную 2D-матрицу, но cholesky возвращает нижнюю треугольную 2D-матрицу)

[V,D]=eig(a)

D,V = linalg.eig(a)

собственные значения \lambda и собственные векторы \bar{v} a, где \lambda\bar{v}=\mathbf{a}\bar{v}

[V,D]=eig(a,b)

D,V = linalg.eig(a, b)

собственные значения \lambda и собственные векторы \bar{v} a, b где \lambda\mathbf{b}\bar{v}=\mathbf{a}\bar{v}

[V,D]=eigs(a,3)

D,V = eigs(a, k = 3)

найти k=3 наибольшие собственные значения и собственные векторы 2D-матрицы, a

[Q,R,P]=qr(a,0)

Q,R = linalg.qr(a)

QR-разложение

[L,U,P]=lu(a) где a==P'*L*U

P,L,U = linalg.lu(a) где a == P@L@U

LU-разложение (примечание: P(MATLAB) == transpose(P(NumPy)))

conjgrad

cg

решение методом сопряжённых градиентов

fft(a)

np.fft(a)

преобразование Фурье a

ifft(a)

np.ifft(a)

обратное преобразование Фурье a

sort(a)

np.sort(a) или a.sort(axis=0)

сортировка каждого столбца 2D-матрицы, a

sort(a, 2)

np.sort(a, axis = 1) или a.sort(axis = 1)

сортировка каждой строки 2D-матрицы, a

[b,I]=sortrows(a,1)

I = np.argsort(a[:, 0]); b = a[I,:]

сохранить массив a как массив b с сортировкой строк по первому столбцу

x = Z\y

x = linalg.lstsq(Z, y)

линейная регрессия вида \mathbf{Zx}=\mathbf{y}

decimate(x, q)

signal.resample(x, np.ceil(len(x)/q))

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

unique(a)

np.unique(a)

вектор уникальных значений в массиве a

squeeze(a)

a.squeeze()

удаление одноэлементных размерностей массива a. Обратите внимание, что MATLAB всегда возвращает массивы 2D и выше, а NumPy — 0D и выше

Примечания

Подматрица: Присвоение подматрицы можно выполнить с помощью списков индексов с использованием команды ix_. Например, для 2D-матрицы a, можно выполнить: ind=[1, 3]; a[np.ix_(ind, ind)] += 100.

Справка: Нет прямого эквивалента команде MATLAB which, но команды help и numpy.source обычно показывают имя файла, где находится функция. Python также имеет модуль inspect (выполните import inspect), который предоставляет getfile инструмент, который часто работает.

ИНДЕКСИРОВАНИЕ: MATLAB использует индексирование, начинающееся с 1, поэтому начальный элемент последовательности имеет индекс 1. Python использует нулевое индексирование, поэтому начальный элемент последовательности имеет индекс 0. Путаница и споры возникают, потому что у каждого есть свои преимущества и недостатки. Индексирование, начинающееся с 1, соответствует общепринятому использованию в естественном языке, где «первый» элемент последовательности имеет индекс 1. Нулевое индексирование упрощает индексирование. См. также текст профессора Эдсгера В. Дейкстры.

ДИАПАЗОНЫ: В MATLAB 0:5 может использоваться как литерал диапазона, так и индекс «среза» (в скобках); однако в Python конструкции, подобные 0:5, только могут использоваться как индекс среза (в квадратных скобках). Таким образом, был создан несколько своеобразный объект r_, чтобы позволить NumPy иметь аналогичный краткий механизм построения диапазонов. Обратите внимание, что r_ не вызывается как функция или конструктор, а индексируется с помощью квадратных скобок, что позволяет использовать синтаксис среза Python в аргументах.

ЛОГИЧЕСКИЕ ОПЕРАЦИИ: & или | в NumPy — это побитовое И/ИЛИ, а в MATLAB & и | — логическое И/ИЛИ. Они могут работать одинаково, но есть важные различия. Если бы вы использовали операторы MATLAB & или |, вы должны использовать NumPy ufuncs logical_and/logical_or. Отличия между операторами MATLAB и NumPy & и |:

  • Ввод нелогического типа {0,1}: выход NumPy — это побитовое И ввода. MATLAB рассматривает любое ненулевое значение как 1 и возвращает логическое И. Например, (3 & 4) в NumPy равно 0, а в MATLAB 3 и 4 считаются логически истинными, и (3 & 4) возвращает 1.
  • Приоритет: оператор & NumPy имеет более высокий приоритет, чем логические операторы, такие как < и >; у MATLAB — обратное.

Если вы знаете, что у вас есть булевы аргументы, вы можете обойтись операторами NumPy, но будьте осторожны со скобками, например, так: z = (x > 1) & (x < 2). Отсутствие операторных форм NumPy logical_and и logical_or — это неудачный результат дизайна Python.

RESHAPE и ЛИНЕЙНОЕ ИНДЕКСИРОВАНИЕ: MATLAB всегда позволяет обращаться к многомерным массивам с помощью скалярных или линейных индексов, NumPy — нет. Линейные индексы распространены в программах MATLAB, например, find() для матрицы возвращают их, в то время как NumPy find ведет себя по-другому. При преобразовании кода MATLAB может потребоваться предварительно преобразовать матрицу в линейную последовательность, выполнить операции индексирования, а затем вернуть исходную форму. Поскольку reshape (обычно) создаёт представления той же памяти, это должно быть достаточно эффективным. Обратите внимание, что порядок обхода, используемый reshape в NumPy, по умолчанию соответствует порядку «C», в то время как MATLAB использует порядок Fortran. Если вы просто преобразуете в линейную последовательность и обратно, это не имеет значения. Но если вы преобразуете reshape из кода MATLAB, который зависит от порядка обхода, то этот код MATLAB: z = reshape(x,3,4); должен стать z = x.reshape(3,4,order='F').copy() в NumPy.

Массив или матрица? Что использовать?

Исторически NumPy предоставляет специальный тип матрицы, np.matrix, который является подклассом ndarray, делающим бинарные операции операциями линейной алгебры. Вы можете видеть его использование в некоторых существующих кодах вместо np.array. Так какой использовать?

Короткий ответ

Используйте массивы.

  • Они поддерживают многомерную алгебру массивов, аналогичную MATLAB.
  • Они являются стандартным типом вектора/матрицы/тензора в NumPy. Многие функции NumPy возвращают массивы, а не матрицы.
  • Существует чёткое различие между поэлементными операциями и операциями линейной алгебры.
  • Можно использовать стандартные векторы или векторы строк/столбцов, если нужно.

До Python 3.5 единственным недостатком использования массивов было то, что для умножения (сведения) двух тензоров (скалярное произведение, умножение матрицы на вектор и т. д.) нужно было использовать dot, а не *. С Python 3.5 можно использовать оператор умножения матриц @.

Учитывая вышесказанное, мы планируем в конечном итоге устареть matrix.

Подробный ответ

NumPy содержит классы array и matrix. Класс array предназначен для многомерных массивов общего назначения для различных видов числовых вычислений, а matrix — для упрощения вычислений линейной алгебры.

  • Операторы * и @, функции dot(), и multiply():

    • Для array, ``*`` означает поэлементное умножение, а ``@`` означает матричное умножение; они имеют связанные функции multiply() и dot(). (До Python 3.5, @ не существовало, и для матричного умножения приходилось использовать dot()).
    • Для matrix, ``*`` означает матричное умножение, а для поэлементного умножения необходимо использовать функцию multiply().
  • Обработка векторов (одномерных массивов)

    • Для array, формы векторов 1xN, Nx1 и N — это все разные вещи. Такие операции, как A[:,1] возвращают одномерный массив формы N, а не двумерный массив формы Nx1. Транспонирование одномерного array ничего не делает.
    • Для matrix, одномерные массивы всегда повышаются до матриц 1xN или Nx1 (строчные или столбцовые векторы). A[:,1] возвращает двумерную матрицу формы Nx1.
  • Обработка многомерных массивов (ndim > 2)

    • array объекты могут иметь количество измерений > 2;
    • matrix объекты всегда имеют ровно два измерения.
  • Удобные атрибуты

    • array имеет атрибут .T, который возвращает транспонированную данные.
    • matrix также имеет атрибуты .H, .I и .A, которые возвращают сопряжённую транспонированную, обратную и asarray() матрицы соответственно.
  • Удобный конструктор

    • Конструктор array принимает (вложенные) Python последовательности в качестве инициализаторов. Как, например, array([[1,2,3],[4,5,6]]).
    • Конструктор matrix дополнительно принимает удобную строковую инициализацию. Как, например, matrix("[1 2 3; 4 5 6]").

Использование того или иного варианта имеет свои преимущества и недостатки:

  • array

    • :) Поэлементное умножение легко выполняется: A*B.
    • :( Необходимо помнить, что для матричного умножения используется свой оператор, @.
    • :) Одномерные массивы можно рассматривать как либо строчные, либо столбцовые векторы. A @ v рассматривает v как столбец, а v @ A рассматривает v как строку. Это может сэкономить время на написание транспонирований.
    • :) array является «стандартным» типом NumPy, поэтому он проходит больше тестов и чаще возвращается сторонними библиотеками, использующими NumPy.
    • :) Удобен для обработки данных любого числа измерений.
    • :) Ближе по смыслу к тензорной алгебре, если вы с ней знакомы.
    • :) Все операции (*, /, +, - и т.д.) являются поэлементными.
    • :( Разряженные матрицы из scipy.sparse не так хорошо взаимодействуют с массивами.
  • matrix

    • :\\ Поведение больше похоже на поведение матриц в MATLAB.
    • <:( Максимальное количество измерений — два. Для хранения трёхмерных данных вам потребуется array или, возможно, Python список matrix.
    • <:( Минимальное количество измерений — два. Векторов быть не может. Они должны быть преобразованы в одностолбцовые или однострочные матрицы.
    • <:( Так как array по умолчанию в NumPy, некоторые функции могут возвращать array даже если вы передадите им matrix в качестве аргумента. Это не должно происходить с функциями NumPy (если это происходит, это ошибка), но сторонние библиотеки на основе NumPy могут не поддерживать сохранение типов так же, как NumPy.
    • :) A*B — это матричное умножение, поэтому выглядит так, как вы пишете его в линейной алгебре (Для Python >= 3.5 обычные массивы имеют аналогичные возможности с оператором @).
    • <:( Поэлементное умножение требует вызова функции, multiply(A,B).
    • <:( Использование перегрузки операторов немного нелогично: * не работает поэлементно, но / работает.
    • Взаимодействие с scipy.sparse немного чище.

Следовательно, использовать array намного предпочтительнее. Мы намерены в конечном счёте отменить matrix.

Настройка вашей среды

В MATLAB основным инструментом для настройки среды является изменение пути поиска с указанием расположения ваших любимых функций. Такие настройки можно поместить в скрипт автозапуска, который MATLAB будет запускать при запуске.

NumPy, а точнее Python, имеют аналогичные возможности.

  • Чтобы изменить путь поиска Python, включив в него расположения ваших собственных модулей, определите переменную среды PYTHONPATH.
  • Чтобы при запуске интерактивного интерпретатора Python выполнялся определённый скрипт, определите переменную среды PYTHONSTARTUP, которая будет содержать имя вашего скрипта автозапуска.

В отличие от MATLAB, где любой элемент в пути можно вызвать немедленно, в Python сначала требуется оператор «import», чтобы функции в конкретном файле стали доступны.

Например, вы можете создать скрипт автозапуска, который выглядит так (Примечание: это всего лишь пример, а не «лучшая практика»):

# Make all numpy available via shorter 'np' prefix
import numpy as np
#
# Make the SciPy linear algebra functions available as linalg.func()
# e.g. linalg.lu, linalg.eig (for general l*B@u==A@u solution)
from scipy import linalg
#
# Define a Hermitian function
def hermitian(A, **kwargs):
    return np.conj(A,**kwargs).T
# Make a shortcut for hermitian:
#    hermitian(A) --> H(A)
H = hermitian

Чтобы использовать устаревшие matrix и другие matlib функции:

# Make all matlib functions accessible at the top level via M.func()
import numpy.matlib as M
# Make some matlib functions accessible directly at the top level via, e.g. rand(3,3)
from numpy.matlib import matrix,rand,zeros,ones,empty,eye

Ссылки

Ещё одна несколько устаревшая ссылка для сравнения MATLAB и NumPy находится по адресу http://mathesaurus.sf.net/

Полный список инструментов для научной работы с Python можно найти на странице специализированного программного обеспечения.

См. Список программного обеспечения Python: сценарии для просмотра списка программ, которые используют Python как скриптовый язык.

MATLAB® и SimuLink® являются зарегистрированными товарными знаками компании The MathWorks, Inc.

© 2005–2021 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.20/user/numpy-for-matlab-users.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API