Nano Hash - криптовалюты, майнинг, программирование

Массив Numpy показывает только уникальные строки

Я хочу, чтобы строки массива были уникальными. В отличие от функции unique numpy, я хочу исключить все строки, которые встречаются более одного раза.

Итак, ввод:

[[1,1],[1,1],[1,2],[2,3],[3,4],[3,4]]

должен привести к выводу

[[1,2],[2,3]].

Я попытался подсчитать появление каждой строки с помощью np.unique(array, return_counts=True) и впоследствии отфильтровать результат с этими записями, равными >1. Я ищу как более эффективный способ сделать это, так и сделать то же самое без возвращаемых счетчиков, поскольку они реализованы не ранее numpy 1.9.

Обновление: размер данных в моем случае всегда равен [m,2], но как только концепция определена, ее должно быть легко перенести на случай [m,n]. В моем особом случае набор данных состоит из целых чисел, но решения не должны ограничиваться этим предположением. Типичный набор данных будет иметь m ~ 10^7.

18.11.2015

  • Каков размер данных входного массива? Всегда ли они целые? 18.11.2015
  • См. ответы здесь для подсчета частоты строк, а затем используйте логическое индексирование. 18.11.2015
  • Я не думаю, что это может быть более эффективно, чем это, потому что создание словаря counts будет O (N). Вы можете использовать collections.Counter, и это должно делать то же самое, если вы не хотите использовать numpy. 18.11.2015
  • Это почти дубликат stackoverflow.com/q/16970982/1461210, за исключением того, что вы также хотите исключать все строки, которые встречаются несколько раз, а не исключать все дубликаты, кроме одного. 18.11.2015
  • В вашем примере показан массив формы (m, 2), а значения в массиве представляют собой небольшие целые числа. Это типичные данные? Или массив может быть (m, n) с n › 2 или содержать целые числа без априорных ограничений для значений или с плавающей запятой? 18.11.2015
  • @ali_m: я не думаю, что это повторяющаяся причина, поскольку numpy.unique ответ на связанный вопрос тривиален. Я явно ищу исключение. 19.11.2015
  • @Dschoni Верно, но как только вы сможете получить уникальные строки с помощью np.unique, будет тривиально исключить повторяющиеся элементы, возвращая количество элементов с помощью np.unique(..., return_counts=True) и фильтруя уникальные индексы строк на основе этого. 19.11.2015
  • @ali_m: Как уже упоминалось в моем исходном сообщении, я ищу решение, которое работает без «return_counts», так как это не реализовано в numpy 1.8. 19.11.2015
  • @Dschoni Вы пробовали опубликованное решение? 19.11.2015
  • @ajcr: Ваше связанное решение кажется самым быстрым, не могли бы вы добавить это как ответ, чтобы я мог его принять? 19.11.2015
  • @Dschoni: решение, которое я предложил на связанной странице, действительно хорошо подходит только для небольших массивов (скажем, 1000 строк или меньше). Если у вас есть массивы большего размера, рекомендуется другой метод поиска счетчиков. Если вы согласны с этим, я могу опубликовать ответ с оговоркой... 19.11.2015
  • @ajcr: В моем случае это полностью устраивает. Тем не менее, я собираюсь сравнить вещи с большими массивами. Это может быть даже достаточно сильным аргументом для перехода на более новую версию numpy;) 23.11.2015

Ответы:


1

Подход №1

Вот один из подходов с использованием lex-sorting и < a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html" rel="nofollow">np.bincount –

# Perform lex sort and get the sorted array version of the input
sorted_idx = np.lexsort(A.T)
sorted_Ar =  A[sorted_idx,:]

# Mask of start of each unique row in sorted array 
mask = np.append(True,np.any(np.diff(sorted_Ar,axis=0),1))

# Get counts of each unique row
unq_count = np.bincount(mask.cumsum()-1) 

# Compare counts to 1 and select the corresponding unique row with the mask
out = sorted_Ar[mask][np.nonzero(unq_count==1)[0]]

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

Подход № 2

Если элементы являются целыми числами, вы можете преобразовать 2D-массив A в 1D-массив, предполагая, что каждая строка является кортежем индексации, и это должно быть довольно эффективным решением. Также обратите внимание, что этот подход сохранит порядок элементов в выводе. Реализация будет -

# Convert 2D array A to a 1D array assuming each row as an indexing tuple
A_1D = A.dot(np.append(A.max(0)[::-1].cumprod()[::-1][1:],1))

# Get sorting indices for the 1D array
sort_idx = A_1D.argsort()

# Mask of start of each unique row in 1D sorted array 
mask = np.append(True,np.diff(A_1D[sort_idx])!=0)

# Get the counts of each unique 1D element
counts = np.bincount(mask.cumsum()-1)

# Select the IDs with counts==1 and thus the unique rows from A
out = A[sort_idx[np.nonzero(mask)[0][counts==1]]]

Тестирование и проверка среды выполнения

Функции -

def unq_rows_v1(A):
    sorted_idx = np.lexsort(A.T)
    sorted_Ar =  A[sorted_idx,:]
    mask = np.append(True,np.any(np.diff(sorted_Ar,axis=0),1))
    unq_count = np.bincount(mask.cumsum()-1) 
    return sorted_Ar[mask][np.nonzero(unq_count==1)[0]]

def unq_rows_v2(A):
    A_1D = A.dot(np.append(A.max(0)[::-1].cumprod()[::-1][1:],1))
    sort_idx = A_1D.argsort()
    mask = np.append(True,np.diff(A_1D[sort_idx])!=0)
    return A[sort_idx[np.nonzero(mask)[0][np.bincount(mask.cumsum()-1)==1]]]

Сроки и проверка выходов -

In [272]: A = np.random.randint(20,30,(10000,5))

In [273]: unq_rows_v1(A).shape
Out[273]: (9051, 5)

In [274]: unq_rows_v2(A).shape
Out[274]: (9051, 5)

In [275]: %timeit unq_rows_v1(A)
100 loops, best of 3: 5.07 ms per loop

In [276]: %timeit unq_rows_v2(A)
1000 loops, best of 3: 1.96 ms per loop
18.11.2015

2

Пакет numpy_indexed (отказ от ответственности: я являюсь его автором) способен эффективно решить эту проблему в полностью векторизованном способ. Я еще не тестировал numpy 1.9, если это все еще актуально, но, возможно, вы захотите попробовать и дайте мне знать. У меня нет оснований полагать, что это не будет работать со старыми версиями numpy.

a = np.random.rand(10000, 3).round(2)
unique, count = npi.count(a)
print(unique[count == 1])

Обратите внимание, что в соответствии с вашим исходным вопросом это решение не ограничено определенным количеством столбцов или dtype.

02.04.2016
Новые материалы

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

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..