2016-03-26 3 views
1

У меня есть два массива numpy a и b, с двадцатью миллионами элементов (число с плавающей точкой). Если элементы комбинации этих двух массивов одинаковы, мы называем это дубликат, который следует удалить из двух массивов. Например,удалить дубликаты элементов из двух массивов numpy

a = numpy.array([1,3,6,3,7,8,3,2,9,10,14,6]) 
b = numpy.array([2,4,15,4,7,9,2,2,0,11,4,15]) 

Из этих двух массивов, мы имеем a[2]&b[2] такие же, как a[11]&b[11], то мы называем его дублировать элемент, который должен быть удален. То же, что и a[1]&b[1] vs a[3]&b[3] Хотя каждый массив имеет повторяющиеся элементы, они не рассматриваются как повторяющиеся элементы. Поэтому я хочу, чтобы возвращаемые массивы были:

a = numpy.array([1,3,6,7,8,3,2,9,10,14]) 
b = numpy.array([2,4,15,7,9,2,2,0,11,4]) 

У любого человека самый умный способ реализовать такое сокращение?

+0

'б [а = Ь! ] 'и' a [a! = b] 'будут работать? – Zero

+0

Я пробовал, он не работает должным образом. –

+0

А, неправильно прочитал вопрос, 'np.vstack ({tuple (row) для строки в np.column_stack ((a, b))})' должен работать, может не дать ваш первый уникальный порядок элементов. – Zero

ответ

2

Сначала вы должны упаковать a и b, чтобы идентифицировать дубликаты. Если значения являются положительными целыми числами (см правку в других случаях), это может быть достигнуто за счет:

base=a.max()+1 
c=a+base*b 

Тогда просто найти уникальные значения в c:

val,ind=np.unique(c,return_index=True) 

и получить соответствующие значения в a и b.

ind.sort() 
print(a[ind]) 
print(b[ind]) 

для устранения дубликата.(Два здесь):

[ 1 3 6 7 8 3 2 9 10 14] 
[ 2 4 15 7 9 2 2 0 11 4] 

EDIT

независимо от типа данных, то с массива может быть сделано как следует, упаковка данных в байтах:

ab=ascontiguousarray(vstack((a,b)).T) 
dtype = 'S'+str(2*a.itemsize) 
c=ab.view(dtype=dtype) 
+0

Спасибо. Значения массива - положительные, но число с плавающей точкой. –

+0

Я предложил более общий подход. –

+0

Большое спасибо. Оно работает. Ваш код является кратким, но не так легко получить его ~~~ –

1

Это делается за один проход и не требует дополнительной памяти для результирующих массивов.

Соедините элементы по каждому индексу и проведите по ним. Следите за тем, какие пары были замечены до сих пор, и счетчик индекса массивов. Когда новая пара ранее не была замечена, индекс увеличится на 1, эффективно вернув их обратно в исходное место. Однако для дублированной пары вы не увеличиваете индекс, эффективно переставляя каждую новую пару на одну позицию влево. В конце удерживайте первое index-е число элементов, чтобы сократить количество массивов.

import itertools as it 

def delete_duplicate_pairs(*arrays): 
    unique = set() 
    arrays = list(arrays) 
    n = range(len(arrays)) 
    index = 0 
    for pair in it.izip(*arrays): 
     if pair not in unique: 
      unique.add(pair) 
      for i in n: 
       arrays[i][index] = pair[i] 
      index += 1 
    return [a[:index] for a in arrays] 

Если вы на Python 2, zip() создает список пар фронт. Если у вас много элементов в ваших массивах, будет более эффективно использовать itertools.izip(), который будет создавать пары по мере их запроса. Однако zip() в Python 3 ведет себя как по умолчанию.

В вашем случае,

>>> import numpy as np 
>>> a = np.array([1,3,6,3,7,8,3,2,9,10,14,6]) 
>>> b = np.array([2,4,15,4,7,9,2,2,0,11,4,15]) 
>>> a, b = delete_duplicate_pairs(a, b) 
>>> a 
array([ 1, 3, 6, 7, 8, 3, 2, 9, 10, 14]) 
>>> b 
array([ 2, 4, 15, 7, 9, 2, 2, 0, 11, 4]) 

Теперь все сводится к тому, что ценности ваши массивы держать. Если у вас есть только значения 0-9, существует только 100 уникальных пар, и большинство элементов будут дублировать, что экономит ваше время. Для 20 миллионов элементов для a и b и содержащих значения только между 0-9, процесс завершается через 6 секунд. Для значений от 0 до 999 требуется 12 секунд.

+0

Большое спасибо, я попробую. Но я забыл упомянуть, что в двух массивах я содержал число с плавающей точкой от 0 до 50. –

Смежные вопросы