Numphp — работа с числовыми векторными массивами и матрицами

habr.png

Сегодня я бы хотел продолжить рассказ про замечательную библиотеку для работы с числовыми массивами в php numphp. Ранее я уже делал краткий обзор на неё тут. С тех пор библиотека обросла функционалом, и, что самое главное, научилась работать с многомерными массивами или матрицами. Про них, в основном и будет идти речь.

Без лишних вступлений сразу пример того, как можно создать матрицу 3 на 4, используя возможности numphp.

$matrix = new np_array([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]);

// matrix
[[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11]]


В результате мы получаем объект np_array. Более того, каждая строка матрицы является также объектом этого типа. Это позволяет делать универсальные выборки.
К примеру, для доступа ко второй строке можно использовать стандартную логику

$row = $matrix[1];

//row
[4, 5, 6, 7]


Но, это было бы неинтересно =)

Благодаря тому, что любой срез матрицы является np_array, мы можем одним махом узнать, к примеру, среднее значение для всей третьей строки

$avg = $matrix[2]->mean();

// avg
9.5


Более того, используя операторы сравнения, можно выбрать все элементы матрицы, удовлетворяющие условию, к примеру больше 5

$result = $matrix[$matrix->gt(5)]
// or
$result = $matrix[$matrix['> 5']]

// result
[ 6,  7,  8,  9, 10, 11]


И получить их сумму

$result = $matrix[$matrix['> 5']]->sum()

// result
51


Как я упомянул выше, мы можем использовать всю мощь срезов, реализованных в numphp, применимо к матрицам тоже. К примеру, взять вторую и третью строку

$result = $matrix['1:3'];

// result
[[ 4,  5,  6,  7],
 [ 8,  9, 10, 11]]


Более детальное описание возможностей можно найти в документации библиотеки.

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


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

$result = $matrix->mul(5); // multiply

// result
[[ 0,  5, 10, 15],
 [20, 25, 30, 35],
 [40, 45, 50, 55]]


Можно так же суммировать матрицу и вектор. В таком случае вектор будет суммироваться с каждой строкой матрицы

$result = $matrix->add([1, 2, 3, 4]);

[[ 1,  3,  5,  7],
 [ 5,  7,  9, 11],
 [ 9, 11, 13, 15]]


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

$diffMartrix = Generator::ones([3, 4]);

// diffMartrix
[[1, 1, 1, 1],
 [1, 1, 1, 1],
 [1, 1, 1, 1]]

$result = $matrix->add($diffMatrix);

// result
[[ 1,  2,  3,  4],
 [ 5,  6,  7,  8],
 [ 9, 10, 11, 12]]


Таким образом можно значительно упростить и ускорить работу с матрицами и векторами.

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


Каждый объект np_array может легко менять свою форму. Под формой я подразумеваю размерность конкретного объекта. К примеру

$list = new np_array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
$list->shape

// [10]

$matrix = new np_array([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]);
$matrix->shape

// [3, 4]


Упрощенно можно считать, что первое число означает количество строк, второе — количество колонок. Но, важно понимать, что библиотека позволяет работать с n-мерными массивами.

Если мы хотим взять нашу матрицу из примера и сделать из неё, скажем, массив точек на координатной доске, мы можем превратить её в матрицу размерности 6×2

$newMatrix = $matrix->reshape([6, 2]);

// newMatrix

[[ 0,  1],
 [ 2,  3],
 [ 4,  5],
 [ 6,  7],
 [ 8,  9],
 [10, 11]]


Если нужно представить n-мерный массив как 1-мерный, можно воспользоваться методом flatten

$result = $matrix->flatten();

// result
[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]


Данный подход удобен для быстрой генерации какого-то тестового набора данных нужной формы.

$result = Generator::arange(1, 15)->reshape([2, 7]);

// result
[[ 1,  2,  3,  4,  5,  6,  7],
 [ 8,  9, 10, 11, 12, 13, 14]]


Последнее что хотел бы описать тут, но далеко не последнее что умеет библиотека — работа с диагональными срезами матриц.

$matrix = Generator::arange(16)->reshape([4, 4]);

// matrix
[[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11],
 [12, 13, 14, 15]]

// get matrix diagonal
[ 0,  5, 10, 15]


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

$matrix = Generator::diagonal([5, 3, 1]);

// matrix
[[5, 0, 0],
 [0, 3, 0],
 [0, 0, 1]]


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

Дополнительные возможности и документацию вы можете найти здесь.

Также, если вы хотите внести свой вклад в развитие — буду рад обсудить любые вопросы.

© Habrahabr.ru