Полное удаление дублированных данных без сохранения одного

1

Я обнаружил, что существует несколько способов удаления дублированных данных. Однако по очевидным причинам ни один из них (по крайней мере, то, что я нашел) полностью удаляет дубликаты, а поддерживает единственную уникальную точку данных. Однако для моей модели я пришел к выводу, что это приводит к некоторому ошибочному поведению и задается вопросом, есть ли способ удалить всех кандидатов из дубликатов. Чтобы быть более ясным, если данные приведены ниже:

x = [[1, 2, 3, 4],
     [1, 2, 3, 4],
     [5, 2, 1, 4],
     [5, 2, 1, 4],
     [3, 4, 2, 4]]

Тогда я хочу ничего, кроме последней строки [3, 4, 2, 4], где дубликаты полностью удаляются (я пытаюсь найти правильное выражение). Я попытался использовать цикл "for" (извлекая данные, которые были не уникальными, и сравнивая их с уникальным набором данных, а затем удаляя их), однако мои данные составляют около 50 тыс., И это занимает слишком много времени. Есть ли эффективный способ сделать это в python?

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

temp = np.ascontiguousarray(raw_input).view(np.dtype((np.void, raw_input.dtype.itemsize*raw_input.shape[1])))
_, idx = np.unique(temp, return_index = True)
input_data = raw_input[idx] # unique input data
output_data = output_label[idx]
Теги:

4 ответа

4
Лучший ответ

Пребывание в "стандартном" Python,

from collections import Counter
c = Counter(map(tuple, x))
output_data = [list(k) for k, v in c.items() if v == 1]

Если вы хотите узнать индексы (в x) строк, которые были удалены (поскольку они дублировали), вы можете сделать следующее:

rem = [idx for idx, k in enumerate(x) if c[tuple(k)] > 1]

Альтернативно (или предпочтительно) с использованием numpy:

u, invidx, cnt = np.unique(x, axis=0, return_inverse=True, return_counts=True)
rem = np.flatnonzero(cnt[invidx] > 1)
output_data = u[cnt == 1]

Пример:

In [1]: from collections import Counter

In [2]: x = [[1, 2, 3, 4],
   ...:      [1, 2, 3, 4],
   ...:      [5, 2, 1, 4],
   ...:      [5, 2, 1, 4],
   ...:      [3, 4, 2, 4]]
   ...:      

In [3]: c = Counter(map(tuple, x))

In [4]: output_data = [list(k) for k, v in c.items() if v == 1]

In [5]: print(output_data)
[[3, 4, 2, 4]]

Пример использования numpy:

In [30]: u, invidx, cnt = np.unique(x, axis=0, return_inverse=True,
    ...: return_counts=True)

In [31]: print(u)
[[1 2 3 4]
 [3 4 2 4]
 [5 2 1 4]]

In [32]: print(invidx)
[0 0 2 2 1]

In [33]: print(cnt)
[2 1 2]

In [34]: rem = np.flatnonzero(cnt[invidx] > 1)

In [35]: output_data = u[cnt == 1]

In [36]: print(rem)
[0 1 2 3]

In [37]: print(output_data)
[[3 4 2 4]]
  • 0
    Спасибо, это то, что я хотел. Однако я понял, что задал этот вопрос без особых подробностей. В настоящее время у меня есть данные в виде массива Numpy. Тем не менее, преобразование в список или наоборот не занимает слишком много времени, поэтому я думаю, что это не большая проблема. То, что я пытаюсь сделать, это удалить все данные более чем в двух случаях. Это можно сделать с помощью ответа, который вы мне дали, однако я не могу связать удаленные данные с метками вывода. Следовательно, мне нужен индекс для удаленных данных или, по крайней мере, какой-нибудь способ установить соединение с меткой.
  • 0
    Будет ли способ удалить строки данных в зависимости от входных данных (что вы сделали в настоящее время) и удалить метку вывода вместе с ней?
Показать ещё 5 комментариев
0

это работает для вас?:

a=[[1,2],[1,2],[2,3],[3,4],[3,4]]
b=a[:]
for i in range(len(a)-1,0,-1):
    if a[i] == a[i-1]:
        del b[i-1:i+1]

# a == [[1, 2], [1, 2], [2, 3], [3, 4], [3, 4]]
# b == [[2, 3]]
0

Проверь это

final_list = list(filter(lambda tup:x.count(list(tup))==1, list(set(map(tuple,x)))))
list(map(list,final_list))
  • 0
    Я не пробовал, и я не собираюсь его преуменьшать, но мне не нравится это решение, потому что оно очень неэффективно: для каждой строки ( tup ) вы просите массив x подсчитать, сколько раз эта строка повторяется. Теперь вы сделали это квадратичной проблемой времени.
  • 0
    final_list = list(filter(lambda tup:x.count(list(tup))==1, list(set(map(tuple,x))))) list(map(list,final_list)) для лучшей сложности случая
-1

Может быть, смените ваши массивы на сеты? Набор поддерживает только уникальные значения.

  • 0
    Проблема здесь в том, что я не хочу просто уникальные значения, но я хочу, чтобы все они были удалены, если есть более двух одинаковых данных.
  • 1
    @CodyChung Я думаю, что вы имели в виду «больше, чем один» (не два).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню