Быстрое сопоставление индексов между двумя массивами Numpy с повторяющимися значениями

Я пытаюсь написать операцию соединения между двумя массивами Numpy и был удивлен, обнаружив, что Numpy recfunctions.join_by не обрабатывает повторяющиеся значения.

Подход, который я использую, заключается в использовании объединяемого столбца и поиске сопоставления индексов между ними. Судя по поиску в Интернете, большинство решений, использующих только Numpy, страдают от одной и той же проблемы: они не могут обрабатывать дубликаты (вы поймете, что я имею в виду, в разделе кода).

Я хочу полностью оставаться в библиотеке Numpy, если это вообще возможно, чтобы воспользоваться преимуществами векторизованных операций, поэтому в идеале нет собственного кода Python, Pandas (по другим причинам) или индексации numpy.

Ниже приведены несколько вопросов, которые я рассмотрел:

Как сопоставить один массив с другим в numpy?Найдите сопоставление индексов между двумя массивами numpyNumpy: для каждого элемента в одном массиве найдите индекс в другом массивеСопоставление индексов между двумя отсортированными частично перекрывающимися массивами numpy

Например, массивы X и Y, которые необходимо объединить по столбцу каждого из них, x и y соответственно.

Отображение определяется как, и f — это то, что мне нужно

mapping = f(x, y)

x = y[mapping]

Так, например,

x = np.array([1,1,2,100])
y = np.array([1,2,3,4,5,6,7])


mapping = [0, 0, 1, -] # '-' indicates masked
x = y[mapping] 

Просматривая подобные вопросы в Интернете, найдите сопоставление от x до y, где есть np.where(np.isin(x,y)), которое дедуплицирует значения. Существует также np.searchsorted(x,y), который вообще не обрабатывает дубликаты в x. Мне интересно, можно ли сделать что-то еще.

Ниже приведено неправильное сопоставление из-за дубликатов в x.

import numpy as np

x = np.array([1,1,2,100])
y = np.array([1,2,3,4,5,6,7])

mapping = np.searchsorted(x, y)
# [0 2 3 3 3 3 3]

Это также неправильное отображение, поскольку отображение должно иметь ту же длину, что и x.

import numpy as np

x = np.array([1,1,2,100])
y = np.array([1,2,3,4,5,6,7])

mapping = np.where(np.isin(x, y))[0]
# [0, 1, 2]

Это join_by образует структурированный массив. Я не изучал этот конкретный вариант, но они recfunctiins обычно создают массив нужного размера и типа. и заполните его по полю кодом Python. То есть они не компилируются, но избегают итераций по (обычно) большему измерению записи.

hpaulj 16.08.2024 03:00

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

hpaulj 16.08.2024 03:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
2
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не уверен, что правильно понял ваш вопрос, но вы можете использовать np.searchsorted с обратными аргументами:

import numpy as np

x = np.array([1, 1, 2, 100])
y = np.array([1, 2, 3, 4, 5, 6, 7])

mapping = np.searchsorted(y, x)
mapping[mapping >= len(y)] = -1  # -1 to indicate "masked" values

print(mapping)

Распечатки:

[ 0  0  1 -1]
Ответ принят как подходящий

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

import numpy as np

# Arrays to be joined
x = np.array([1, 1, 2, 100, 4, 5, 3, 75])
y = np.array([1, 2, 3, 4, 5, 6, 7])

# Get mask with True and False values
mask = np.isin(x, y)
# [ True  True  True False  True  True  True False]

# Get indices of every element
indices = np.searchsorted(y, x)
# [0  0  1  7  3  4  2  7]

# Match indices with mask
mapping = np.where(mask, indices, -1)
# [ 0  0  1 -1  3  4  2 -1]

Мы создаем маску, получаем индексы и затем сопоставляем индексы с маской. Значения, которых нет в y, получают значение -1

Это решение полностью остается внутри библиотеки Numpy.

Другие вопросы по теме