Удаление повторяющихся столбцов и строк из массива NumPy 2D
Я использую массив двумерных фигур для хранения пар долгот + широт. В какой-то момент я должен объединить два из этих 2D-массивов, а затем удалить любую дублируемую запись. Я искал функцию, похожую на numpy.unique, но мне не повезло. Любая реализация, которую я выполнял
мышление выглядит очень "неоптимизированным". Например, я пытаюсь преобразовать массив в список кортежей, удалив дубликаты с помощью набора, а затем снова перейдя в массив:
coordskeys = np.array(list(set([tuple(x) for x in coordskeys])))
Есть ли существующие решения, поэтому я не изобретаю колесо?
Чтобы было ясно, я ищу:
>>> a = np.array([[1, 1], [2, 3], [1, 1], [5, 4], [2, 3]])
>>> unique_rows(a)
array([[1, 1], [2, 3],[5, 4]])
Кстати, я хотел использовать только список кортежей для него, но списки были настолько большими, что они потребляли мой 4Gb RAM + 4Gb swap (массивы numpy более эффективны с точки зрения памяти).
Ответы
Ответ 1
Здесь одна идея, это займет немного работы, но может быть довольно быстро. Я дам вам 1-й случай и дам вам понять, как его расширить до 2d. Следующая функция находит уникальные элементы массива 1d:
import numpy as np
def unique(a):
a = np.sort(a)
b = np.diff(a)
b = np.r_[1, b]
return a[b != 0]
Теперь, чтобы расширить его до 2d, вам нужно изменить две вещи. Вам нужно будет выяснить, как это сделать самостоятельно, важная вещь в сортировке будет заключаться в том, что две идентичные записи оказываются рядом друг с другом. Во-вторых, вам нужно сделать что-то вроде (b != 0).all(axis)
, потому что вы хотите сравнить всю строку/столбец. Дайте мне знать, если этого достаточно, чтобы вы начали.
обновлено: с некоторой помощью с doug я думаю, что это должно работать для случая 2d.
import numpy as np
def unique(a):
order = np.lexsort(a.T)
a = a[order]
diff = np.diff(a, axis=0)
ui = np.ones(len(a), 'bool')
ui[1:] = (diff != 0).any(axis=1)
return a[ui]
Ответ 2
Это должно сделать трюк:
def unique_rows(a):
a = np.ascontiguousarray(a)
unique_a = np.unique(a.view([('', a.dtype)]*a.shape[1]))
return unique_a.view(a.dtype).reshape((unique_a.shape[0], a.shape[1]))
Пример:
>>> a = np.array([[1, 1], [2, 3], [1, 1], [5, 4], [2, 3]])
>>> unique_rows(a)
array([[1, 1],
[2, 3],
[5, 4]])
Ответ 3
Мой метод заключается в том, чтобы превратить массив 2d в 1d комплексный массив, где действительная часть - 1-й столбец, мнимая часть - 2-й столбец. Затем используйте np.unique. Хотя это будет работать только с двумя столбцами.
import numpy as np
def unique2d(a):
x, y = a.T
b = x + y*1.0j
idx = np.unique(b,return_index=True)[1]
return a[idx]
Пример -
a = np.array([[1, 1], [2, 3], [1, 1], [5, 4], [2, 3]])
unique2d(a)
array([[1, 1],
[2, 3],
[5, 4]])
Ответ 4
>>> import numpy as NP
>>> # create a 2D NumPy array with some duplicate rows
>>> A
array([[1, 1, 1, 5, 7],
[5, 4, 5, 4, 7],
[7, 9, 4, 7, 8],
[5, 4, 5, 4, 7],
[1, 1, 1, 5, 7],
[5, 4, 5, 4, 7],
[7, 9, 4, 7, 8],
[5, 4, 5, 4, 7],
[7, 9, 4, 7, 8]])
>>> # first, sort the 2D NumPy array row-wise so dups will be contiguous
>>> # and rows are preserved
>>> a, b, c, d, e = A.T # create the keys for to pass to lexsort
>>> ndx = NP.lexsort((a, b, c, d, e))
>>> ndx
array([1, 3, 5, 7, 0, 4, 2, 6, 8])
>>> A = A[ndx,]
>>> # now diff by row
>>> A1 = NP.diff(A, axis=0)
>>> A1
array([[0, 0, 0, 0, 0],
[4, 3, 3, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 1, 0, 0],
[2, 5, 0, 2, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
>>> # the index array holding the location of each duplicate row
>>> ndx = NP.any(A1, axis=1)
>>> ndx
array([False, True, False, True, True, True, False, False], dtype=bool)
>>> # retrieve the duplicate rows:
>>> A[1:,:][ndx,]
array([[7, 9, 4, 7, 8],
[1, 1, 1, 5, 7],
[5, 4, 5, 4, 7],
[7, 9, 4, 7, 8]])
Ответ 5
Пакет numpy_indexed (отказ от ответственности: я являюсь его автором) обертывает решение, размещенное user545424 в приятном и проверенном интерфейсе, а также множество связанных функций
import numpy_indexed as npi
npi.unique(coordskeys)
Ответ 6
поскольку вы ссылаетесь на numpy.unique, вы не заботитесь о сохранении первоначального заказа, правильно? преобразование в множество, которое удаляет дубликат, а затем обратно в список часто используется идиома:
>>> x = [(1, 1), (2, 3), (1, 1), (5, 4), (2, 3)]
>>> y = list(set(x))
>>> y
[(5, 4), (2, 3), (1, 1)]
>>>