Удаление повторяющихся строк массива numpy

171
10

Как удалить повторяющиеся строки 2-мерного массива numpy?


data = np.array([[1,8,3,3,4],
[1,8,9,9,4],
[1,8,3,3,4]])

Ответ должен быть следующим:


ans = array([[1,8,3,3,4],
[1,8,9,9,4]])

Если есть две строки, которые являются одинаковыми, я хотел бы удалить одну "повторяющуюся" строку.

спросил(а) 2021-01-19T15:17:47+03:00 2 месяца, 3 недели назад
1
Решение
216

Вы можете использовать numpy unique. Поскольку вам нужны уникальные строки, нам нужно поместить их в кортежи:


import numpy as np

data = np.array([[1,8,3,3,4],
[1,8,9,9,4],
[1,8,3,3,4]])


просто применяя np.unique к массиву data, это приведет к следующему:


>>> uniques
array([1, 3, 4, 8, 9])

выводит уникальные элементы в списке. Поэтому, помещая их в кортежи, результат:


new_array = [tuple(row) for row in data]
uniques = np.unique(new_array)

который печатает:


>>> uniques
array([[1, 8, 3, 3, 4],
[1, 8, 9, 9, 4]])

ответил(а) 2021-01-19T15:17:47+03:00 2 месяца, 3 недели назад
169

Один подход с lex-sorting -


# Perform lex sort and get sorted data
sorted_idx = np.lexsort(data.T)
sorted_data = data[sorted_idx,:]

# Get unique row mask
row_mask = np.append([True],np.any(np.diff(sorted_data,axis=0),1))

# Get unique rows
out = sorted_data[row_mask]


Пример прогона -


In [199]: data
Out[199]:
array([[1, 8, 3, 3, 4],
[1, 8, 9, 9, 4],
[1, 8, 3, 3, 4],
[1, 8, 3, 3, 4],
[1, 8, 0, 3, 4],
[1, 8, 9, 9, 4]])

In [200]: sorted_idx = np.lexsort(data.T)
...: sorted_data = data[sorted_idx,:]
...: row_mask = np.append([True],np.any(np.diff(sorted_data,axis=0),1))
...: out = sorted_data[row_mask]
...:

In [201]: out
Out[201]:
array([[1, 8, 0, 3, 4],
[1, 8, 3, 3, 4],
[1, 8, 9, 9, 4]])

Тесты времени выполнения -


В этом разделе рассматриваются все подходы, предложенные в представленных решениях.


In [34]: data = np.random.randint(0,10,(10000,10))

In [35]: def tuple_based(data):
...: new_array = [tuple(row) for row in data]
...: return np.unique(new_array)
...:
...: def lexsort_based(data):
...: sorted_data = data[np.lexsort(data.T),:]
...: row_mask = np.append([True],np.any(np.diff(sorted_data,axis=0),1))
...: return sorted_data[row_mask]
...:
...: def unique_based(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]))
...:

In [36]: %timeit tuple_based(data)
10 loops, best of 3: 63.1 ms per loop

In [37]: %timeit lexsort_based(data)
100 loops, best of 3: 8.92 ms per loop

In [38]: %timeit unique_based(data)
10 loops, best of 3: 29.1 ms per loop

ответил(а) 2021-01-19T15:17:47+03:00 2 месяца, 3 недели назад
61

Простым решением может быть:


import numpy as np
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]))

data = np.array([[1,8,3,3,4],
[1,8,9,9,4],
[1,8,3,3,4]])

print unique_rows(data)
#prints:
[[1 8 3 3 4]
[1 8 9 9 4]]


Вы можете проверить этот для решения многих других проблем.

ответил(а) 2021-01-19T15:17:47+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема