проверить, являются ли строки из набора индексов дубликатами или нет, и восстановить - PullRequest
0 голосов
/ 04 февраля 2019

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

Например,

>>>> a
array([[1, 0, 1, 0],
       [0, 0, 1, 1],
       [1, 0, 1, 0],
       [0, 0, 1, 1],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
])

Мне дан набор индексов (0,2,3,4,6,7).Из набора строки, соответствующие (0,2) и (4,6,7), являются дубликатами.Я хочу, чтобы полученная матрица с удаленными дубликатами (как показано ниже)

>>>> b
array([[1, 0, 1, 0],
       [0, 0, 1, 1],
       [0, 0, 1, 1],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
])

и метод восстановления матрицы 'a' из 'b'

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Если порядок в выходном массиве не имеет значения, то, вероятно, вы можете просто использовать ответ Eelco Hoogendoorn .Однако, если вы хотите сохранить тот же относительный порядок, что и в исходном массиве, вот еще один возможный подход.

import numpy as np

a = np.array([
    [1, 0, 1, 0],
    [0, 0, 1, 1],
    [1, 0, 1, 0],
    [0, 0, 1, 1],
    [1, 1, 1, 0],
    [1, 1, 1, 0],
    [1, 1, 1, 0],
    [1, 1, 1, 0],
])
idx = np.array([0, 2, 3, 4, 6, 7])
# Make an array of row numbers
r = np.arange(len(a))
# Replace row numbers in idx with -1
# (use assume_unique only if indices in idx are unique)
r[np.isin(r, idx, assume_unique=True)] = -1
# Add the column to the array
a2 = np.concatenate([a, r[:, np.newaxis]], axis=-1)
# Find unique indices and inverse indices
_, uniq_idx, inv_idx = np.unique(a2, return_index=True, return_inverse=True, axis=0)
# Sort indices to make output array and inverse indices
s = np.argsort(uniq_idx)
a_uniq = a[uniq_idx[s]]
inv_idx = s[inv_idx]
print(a_uniq)
# [[1 0 1 0]
#  [0 0 1 1]
#  [0 0 1 1]
#  [1 1 1 0]
#  [1 1 1 0]]
print(np.all(a_uniq[inv_idx] == a))
# True

РЕДАКТИРОВАТЬ: Некоторое дальнейшее объяснение.

Идея в решении вышеприменяется np.unique, но таким образом, что строки, не включенные в idx, не затрагиваются этим.Чтобы сделать это, вы можете просто добавить новый номер в каждую строку.Для строк, включенных в idx, это число всегда будет -1, а для остальных строк это будет разное число для каждого.Таким образом, невозможно, чтобы строки, не входящие в idx, были удалены с помощью np.unique.Для этого я строю r, сначала с np.arange(len(a)), что дает вам число в строке:

[0 1 2 3 4 5 6 7]

Затем я проверяю, какие из них находятся в idx с np.isin(r, idx, assume_unique=True)(assume_unique можно использовать только в том случае, если элементы в idx гарантированно являются уникальными), поэтому r[np.isin(r, idx, assume_unique=True)] = -1 превратит все индексы idx в -1:

[-1  1 -1 -1 -1  5 -1 -1]

, которые добавляются как новыестолбец в a в a2:

[[ 1  0  1  0 -1]
 [ 0  0  1  1  1]
 [ 1  0  1  0 -1]
 [ 0  0  1  1 -1]
 [ 1  1  1  0 -1]
 [ 1  1  1  0  5]
 [ 1  1  1  0 -1]
 [ 1  1  1  0 -1]]

Теперь нужно просто применить np.unique к a2.Как и ожидалось, только строки в idx могут быть удалены.Однако, поскольку мы хотим сохранить исходный относительный порядок, мы не можем использовать вывод np.unique, потому что он отсортирован.Мы используем return_index и return_inverse, чтобы получить индексы, которые составляют массив уникальных строк, и индексы, которые возвращают вас к исходному массиву, и фактически отбрасывают новый массив.

Для формирования окончательного массиваВам нужно отсортировать uniq_idx, чтобы сохранить относительный порядок, а затем inv_idx соответственно.np.argsort дает вам индексы, которые сортируют uniq_idx в s.uniq_idx[s] - это просто отсортированный массив уникальных индексов строк, а s[inv_idx] отобразит каждый обратный индекс в inv_idx на соответствующий индекс в массиве, который был восстановлен.Итак, наконец, a[uniq_idx[s]] дает вам выходной массив, а новый inv_idx возвращает вас к исходному.

0 голосов
/ 04 февраля 2019

Такое чувство, что вы могли бы сформулировать свой вопрос на более высоком уровне, чтобы получить более элегантное решение;но это, кажется, решает буквальную проблему как заявлено.

idx = [0,2,3,4,6,7]
b = np.concatenate([np.unique(a[idx], axis=0), np.delete(a, idx, axis=0)], axis=0)
...