Меню

Numpy сравнить две матрицы



Сравнение двух матриц по строкам по вхождению в NumPy

Предположим, у меня есть две матрицы NumPy (или Pandas DataFrames, хотя я предполагаю, что в NumPy это будет быстрее).

Для каждого вектора-строки в arr1 я хочу посчитать вхождение этого вектора-строки в arr2 и сгенерировать вектор этих отсчетов. Таким образом, для этого примера, результат будет

Какой эффективный способ сделать это?

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

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

Второй подход : я мог бы сохранить количество строк в collection.Counter, а затем просто получить к нему доступ с помощью apply_along_axis .

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

3 ответа

Вот подход NumPy после преобразования входных данных в одномерные эквиваленты, а затем сортировки и использования np.searchsorted вместе с np.bincount для подсчета —

Панды были бы хорошим инструментом для этого. Вы можете поместить arr2 в фрейм данных и использовать метод groupby для подсчета количества вхождений каждой строки, а затем переиндексировать результат с помощью arr1.

Задержки
Сначала создайте намного больше данных

Теперь время это:

1 цикл, лучшее из 3: 704 мс на цикл

10 циклов, лучшее из 3: 53,8 мс на цикл

Начните с сбора эквивалентов линейного индекса для индексов строк и столбцов a2 , используя np.ravel_multi_index . Добавьте 1, чтобы учесть индексирование 0 на основе numpy. Получить соответствующее количество уникальных строк, представленных через np.unique() . Затем найдите подходящие строки между уникальными строками a2 и a1 , расширив a1 до нового измерения по направлению к правой оси (, также известный как широковещательная рассылка ) и извлекать индексы ненулевых строк для обоих массивов.

Инициализировать массив нулей и заполнить его значения путем нарезки на основе полученных индексов.

Для: a2 = a2.repeat(100000, axis=0)

Источник

Матрицы в Python и массивы NumPy

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

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

Матрицы в Python

Python не имеет встроенного типа данных для матриц. Но можно рассматривать список как матрицу. Например:

Этот список является матрицей на 2 строки и 3 столбца.

Обязательно ознакомьтесь с документацией по спискам Python , прежде чем продолжить читать эту статью.

Давайте посмотрим, как работать с вложенным списком.

Когда мы запустим эту программу, результат будет следующий:

Использование вложенных списков в качестве матрицы подходит для простых вычислительных задач. Но в Python есть более эффективный способ работы с матрицами – NumPy .

NumPy массивы в Python

NumPy — это расширение для научных вычислений, которое поддерживает мощный объект N-мерного массива. Прежде чем использовать NumPy, необходимо установить его. Для получения дополнительной информации,

  • Ознакомьтесь: Как установить NumPy Python?
  • Если вы работаете в Windows, скачайте и установите дистрибутив anaconda Python. Он поставляется вместе с NumPy и другими расширениями.

После установки NumPy можно импортировать и использовать его.

NumPy предоставляет собой многомерный массив чисел (который на самом деле является объектом). Давайте рассмотрим приведенный ниже пример:

Как видите, класс массива NumPy называется ndarray.

Как создать массив NumPy?

Существует несколько способов создания массивов NumPy.

Массив целых чисел, чисел с плавающей точкой и составных чисел

Когда вы запустите эту программу, результат будет следующий:

Массив нулей и единиц

Здесь мы указали dtype — 32 бита (4 байта). Следовательно, этот массив может принимать значения от -2 -31 до 2 -31 -1.

Использование arange() и shape()

Узнайте больше о других способах создания массива NumPy .

Операции с матрицами

Выше мы привели пример сложение, умножение матриц и транспонирование матрицы. Мы использовали вложенные списки, прежде чем создавать эти программы. Рассмотрим, как выполнить ту же задачу, используя массив NumPy.

Сложение двух матриц или сумма элементов массива Python

Мы используем оператор +, чтобы сложить соответствующие элементы двух матриц NumPy.

Умножение двух матриц Python

Чтобы умножить две матрицы, мы используем метод dot(). Узнайте больше о том, как работает numpy.dot .

Примечание: * используется для умножения массива (умножения соответствующих элементов двух массивов), а не умножения матрицы.

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

Мы используем numpy.transpose для вычисления транспонирования матрицы.

Как видите, NumPy значительно упростил нашу задачу.

Доступ к элементам матрицы, строкам и столбца

Доступ к элементам матрицы

Также можно получить доступ к элементам матрицы, используя индекс. Начнем с одномерного массива NumPy.

Когда вы запустите эту программу, результат будет следующий:

Теперь выясним, как получить доступ к элементам двухмерного массива (который в основном представляет собой матрицу).

Когда мы запустим эту программу, результат будет следующий:

Доступ к строкам матрицы

Когда мы запустим эту программу, результат будет следующий:

Доступ к столбцам матрицы

Когда мы запустим эту программу, результат будет следующий:

Если вы не знаете, как работает приведенный выше код, прочтите раздел «Разделение матрицы».

Разделение матрицы

Разделение одномерного массива NumPy аналогично разделению списка. Рассмотрим пример:

Теперь посмотрим, как разделить матрицу.

Читайте также:  Мини бультерьер сравнение с бультерьером стандарт

Использование NumPy вместо вложенных списков значительно упрощает работу с матрицами. Мы рекомендуем детально изучить пакет NumPy, если вы планируете использовать Python для анализа данных.

Источник

NumPy в Python. Часть 3

И снова здравствуйте! Продолжаем наш цикл статей по переводу мана о numpy. Приятного чтения.

Булево сравнение может быть использовано для поэлементного сравнения массивов одинаковых длин. Возвращаемое значение это массив булевых True/False значений:

Результат сравнения может быть сохранен в массиве:

Массивы могут быть сравнены с одиночным значением:

Операторы any и all могут быть использованы для определения истинны ли хотя бы один или все элементы соответственно:

Комбинированные булевы выражения могут быть применены к массивам по принципу элемент — элемент используя специальные функции logical_and, logical_or и logical_not:

Функция where создает новый массив из двух других массивов одинаковых длин используя булев фильтр для выбора межу двумя элементами. Базовый синтаксис: where(boolarray,
truearray, falsearray):

С функцией where так же может быть реализовано «массовое сравнение»:

Некоторые функции дают возможность тестировать значения в массиве. Функция nonzero возвращает кортеж индексов ненулевых значений. Количество элементов в кортеже равно количеству осей в массиве:

Также можно проверить значения на конечность и NaN(not a number):

Хотя здесь мы использовали константы numpy чтобы добавить значения NaN и бесконечность, они могут быть результатами применения стандартных математических операций.

Выбор элементов массива и манипуляция с ними

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

Булевы массивы могут быть использованы как массивы для фильтрации:

Стоит заметить, что когда мы передаем булев массив a>=6 как индекс для операции доступа по индексу массива a, возвращаемый массив будет хранить только True значения. Также мы можем записать массив для фильтрации в переменную:

Более замысловатая фильтрация может быть достигнута использованием булевых выражений:

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

Иными словами, когда мы используем b для получения элементов из a, мы берем 0-й, 0-й, 1-й, 3-й, 2-й и 1-й элементы a в этом порядке. Списки также могут быть использованы как массивы для фильтрации:

Для многомерных массивов, нам необходимо передать несколько одномерных целочисленных массивов в оператор доступа индексу (Прим. переводчика: в нашем случае индексы это массивы) для каждой оси. Потом каждый из массивов проходит такую последовательность: первый элемент соответствует индексу строки, который является первым элементом массива b, второй элемент соответствует индексу столбца, который является первым элементом массива c и так далее. (Прим. переводчика: первый массив [2, 2] и второй [1, 4], имеем на выходе элементы с индексами [2, 1] и [2, 4]) Пример:

Специальная функция take доступна для выполнения выборки с целочисленными массивами. Это работает также как и использования оператора взятия по индексу:

Функция take также предоставляет аргумент axis (ось) для взятия подсекции многомерного массива вдоль какой-либо оси. (Прим. переводчика: по строкам или столбцам (для двумерных массивов)).

В противоположность к функции take есть функция put, которая будет брать значения из исходного массива и записывать их на специфические индексы в другом put-массиве.

Заметим, что значение 7 из исходного массива b не было использовано, так как только 2 индекса [0, 3] указаны. Исходный массив будет повторен если необходимо в случае не соответствия длин:

Векторная и матричная математика

NumPy обеспечивает много функций для работы с векторами и матрицами. Функция dot возвращает скалярное произведение векторов:

Функция dot также может умножать матрицы:

Также можно получить скалярное, тензорное и внешнее произведение матриц и векторов. Заметим, что для векторов внутреннее и скалярное произведение совпадает.

NumPy также предоставляет набор встроенных функций и методов для работы с линейной алгеброй. Это всё можно найти в под-модуле linalg. Этими модулями также можно оперировать с вырожденными и невырожденными матрицами. Определитель матрицы ищется таким образом:

Также можно найти собственный вектор и собственное значение матрицы:

Невырожденная матрица может быть найдена так:

Одиночное разложение (аналог диагонализации не квадратной матрицы) может быть достигнут так:

Заканчиваем третью часть. Удачи и до скорого!

Источник

7. Математика в NumPy

Когда дело доходит до математики и вычислений над какими-то наборами данных всегда появляется один итот же вопрос — что дороже, время потраченное на программную реализацию алгоритма вычислений или время компьютера, которое необходимо компьютеру для выполнения данной программы. Ответ очень прост, если за стеной вашего кабинета нет суперкомпьютера, то ваше время несомненно дороже. Да, знание ассемблера, C или Fortran позволит вам создавать очень быстрые программы, но на создание потребуется гораздо больше времени, чем в случае создания тех же программ на языке Python.

NumPy — это удачная попытка соединить скорость вычислений на языках C и Fortran со скоростью разработки программ на языке Python. Еще одним огромным достоинством NumPy является большой набор уже готовых математических функций, охватывающий многие разделы математики. Причём, большинство данных функций могут быть легко оптимизированы под конкретную задачу. А механизм транслирования NumPy позволяет избежать написания большого количества циклов, особенно вложенных, которые так часто встречаются при работе с многомерными массивами.

Читайте также:  Сравнение стандартов управления качеством

7.1. Базовые математические операции

Пожалуй, первое с чего стоит начать, так это с того, что массивы NumPy могут быть обычными операндами в математических выражениях:

Для выполнения таких операций на Python, мы были вынуждены писать циклы. Писать такие циклы в NumPy, нет никакой необходимости, потому что все операции и так выполняются поэлементно:

Точно так же обстоят дела и с математическими функциями:

Такие операции как += , -= , *= , /= и прочие подобные, могут применяться к массивам и так же выполняются поэлементно. Они не создают новый массив, а изменяют старый:

При работе с массивами разного типа, тип результирующего массива приводится к более общему:

Применение логических операций к массивам, так же возможно и так же выполняется поэлементно. Результатом таких операций является массив булевых значений ( True и False ):

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

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

Хотя, если честно, их размеры должны быть не равны, а должны быть совместимыми. Если их размеры совместимы, т.е. один массив может быть растянут до размеров другого, то в дело включается механизм транслирования массивов NumPy. Этот механизм очень прост, но имеет весьма специфичные нюансы. Рассмотрим простой пример:

В данном примере массив b может быть растянут до размеров массива a и станет абсолютно идентичен массиву c. Транслирование массивов невероятно удобно, так как позволяет избежать создания множества вложенных и невложенных циклов. К тому же в NumPy этот механизм реализован для максимально быстрого выполнения. Так что используйте транслирование везде, где это возможно в ваших вычислениях.

Вычисление суммы всех элементов в массиве и прочие унарные операции в NumPy реализованы как методы класса ndarray :

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

7.1.1. Значения -inf, inf и nan

Возможно вы обратили внимание на то, что когда мы вычисляли натуральный логарифм массива, среди значений которого был ноль, не появилось абсолютно никакой ошибки, а сам логарифм стал равен значению -inf (минус бесконечность). Убедимся в этом еще раз:

Более того, в NumPy мы даже можем делить на ноль:

NumPy предупредил нас о том, что встретил деление на ноль, но тем не менее выдал ответ inf (плюс бесконечность). Дело в том, что с математической точки зрения все абсолютно верно — если вы что-то делите на бесконечно малое значение то в результате получете значение, которое окажется бесконечно большим. Если результатом математической операции является плюс или минус бесконечность, то логичнее выдать значение inf или -inf чем выдавать ошибку.

В NumPy есть еще одно специальное значение — nan . Данное значение выдается тогда, когда результат вычислений не удается определить:

Заметьте, что NumPy нас просто предупредил о том, что ему попалось недопустимое значение, но ошибки не возникло. Дело в том, что в реальных вычислениях значения nan , inf или -inf встречается очень часто, поэтому появление этого значения проще обрабатывать специальными методами (функции numpy.isnan() и numpy.isinf() ), чем постоянно лицезреть сообщения об ошибках.

Новичкам, довольно трудно привыкнуть, к тому что в недрах компьютера вся арифметика на самом деле является двоичной и с этим связано очень много казусов. Во первых не совсем понятно, когда ждать появления значений -inf и inf :

Число 1.633123935319537e+16 появилось потому что в NumPy выполняются арифметические, а не символьные вычисления, т. е. число π хранится в памяти компьютера не как знание о том, что это математическая константа с бесконечным количеством десятичных знаков после запятой, а как обычное число с десятичной точкой (десятичная дробь) равная числу π с очень маленькой, но все же, погрешностью:

NumPy отличает предельные случаи, когда вычисления выполнить невозможно, например, деление на ноль. В таких случаях появляются значения -inf , inf и nan . Если из-за самых незначительных погрешностей вычисления все же возможны, то NumPy их обязательно выполнит. В этих случаях вместо значений -inf или inf у вас будут появляться самые маленькие или самые большие числа, которые возможно представить на вашем компьютере.

Тем не менее и на этом сюрпризы не заканчиваются. Если число 1.633123935319537e+16 является самым больши, которое может появиться при вычислениях, оно вполне ожидаемо должно появиться в самых разных ситуациях. Например:

То, есть какая-то, длинная арифметика все же доступна — очень хорошая новость, для лбителей криптографии и теории чисел. Но иногда:

В заключение могу лишь сказать, что все предельные случаи требуют кардинальных решений. Некоторые решения имеются в самом NumPy, некоторые предоставляют другие пакеты. Если вам необходимы точные решения, то лучше обратиться к системам компьютерной алгебры и символьных вычислений, например пакету SymPy — маленький, но мощьный пакет Python для символьных вычислений. Если вы решили отправиться в самые дебри теории чисел, алгебры и криптографии, то лучшим решением окажется программа GAP. Программа GAP не является программой Python, но имеет Python интерфейс в замечательной программе Sage, которая определенно заслуживает вашего внмания.

Читайте также:  Процессор кирин 960 сравнение

7.2. Линейная алгебра

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

Произведение одномерных массивов представляет собой скалярное произведение векторов:

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

При этом размеры матриц (массивов) должны быть либо равны, а сами матрицы квадратными, либо быть согласованными, т.е. если размеры матрицы А равны [m,k], то размеры матрицы В должны быть равны [k,n]:

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

Квадратные матрицы можно возводить в степень n т.е. умнажать сами на себя n раз:

Довольно часто приходится вычислять ранг матриц:

Еще чаще приходится вычислять определитель матриц ,хотя результат вас может немного удивить:

В данном случае, из-за двоичной арифметики, результат не целое число и округлять до ближайшего целого прийдется вручную. Это связано с тем, что алгоритм вычисления определителя использует LU-разложение — это намного быстрее чем обычный алгоритм, но за скорость все же приходится немного заплатить ручным округлением (конечно, если таковое требуется):

Вычисление обратных матриц:

Решение систем линейных уравнений:

7.3. Статистика

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

Элементарные статистические функции:

Средние значения элементов массива и их отклонения:

Корреляционные коэфициенты и ковариационные матрицы величин:

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

7.4. Генерация случайных значений

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

Получение простых случайных данных:

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

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

7.5. Дискретное преобразование Фурье

Если данные в ваших массивах — это сигналы: звуки, изображения, радиоволны, котировки акций и т.д., то вам наверняка понадобится дискретное преобразование Фурье. В NumPy представлены методы быстрого дискретного преобразования Фурье для одномерных, двумерных и многомерных сигналов, а так же некоторые вспомогательные функции. Рассмотрим некоторые простые примеры.

Одномерное дискретное преобразование Фурье:

Двумерное дискретное преобразование Фурье:

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

7.6. Прочие математические разделы

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

7.6.1. Множества

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

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

Функция unique() так же позволяет получить индексы входного массива с первым вхождением уникальных элементов, а так же индексы уникального массива которые восстанавливают исходный массив:

Так же имеется ряд других полезных функций:

7.6.2. Логические операции

Логические функции NumPy, условно, можно разделить на два множества: первое — позволяет определять специфику элементов массива и самого массива; второе — обычные логические операции которые действуют над массивами поэлементно.

Иногда, возникает потребность определить тип элементов:

Привычные нам логические операции выполняются над массивами булевых значений (массивы из значений True и False ):

Помимо всего прочего, NumPy позволяет производить различные сравнения:

7.6.3. Многочлены

Многочлены, довольно часто, встречаются в самых разных областях: физика, инженерное дело, теория приближений, криптография, теория вероятностей, комбинаторика и т.д. Многочлены определенного вида выделяются в особые классы, каждый из которых имеет свою нишу применения. В NumPy представлены функции для работы с классами многочленов Чебышёва, Лежандра, Лагерра и Эрмита. Помимо прочего, NumPy предоставляет широкий набор функций для работы с полиномами в общем виде, т.е. полиномы любого вида (Бернулли, Гегенбауэра, Шапиро, Якоби, Роджерса в том числе) могут быть легко сконструированы пользователем самостоятельно.

Рассмотрим базовые функции для работы с полиномами:

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

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

Источник