2015-02-05 2 views
1

Привет всем, и, пожалуйста, извините мое ограниченное программирование knoweledge. У меня есть два массива типа:Сравнение массивов различных массивов длины в numpy

A =([[ 0.10111977, 0.5511177 , 0.49532397, 0.42136468, 0.43345532], 
    [ 0.3812068 , 0.97679566, 0.20473656, 0.40256096, 0.32423426], 
    [ 0.2387294 , 0.88714084, 0.01064819, 0.48275173, 0.78234234]]) 

B = ([[ 0.10111977, 0.5511177 , 0.49532397], 
     [ 0.2387294 , 0.88714084, 0.01064819]]) 

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

C =([[ 0.10111977, 0.5511177 , 0.49532397, 0.42136468, 0.43345532], 
    [ 0.2387294 , 0.88714084, 0.01064819, 0.48275173, 0.78234234]]) 

УПРОЩЕННОЙ (скотина сила) решение, которое я пытался это сделать что-то вроде:

for rowB in B: 
    for rowA in A: 
     if A[rowA,0]==B[rowB,0] and A[rowA,1]==B[rowB,1] and A[rowA,2]==B[rowB,2]: 
      C.extend(row) 
      continue 

теперь это будет работать, но, как я сказал, мои наборы данных огромен, и он принимает навсегда. Есть ли более быстрый \ более быстрый способ сделать это? Я думал об интерполяции, но я не вижу, как это можно сделать с этими данными.

+0

Я хочу сказать, что-то вроде изменить ваш 'if' условие: 'cmp (rowB, rowA [: 3]) == 0' - это упростит чтение, но не знает, если он быстрее. Ваша проблема в том, что вы проходите через A для каждой строки B, и я не думаю, что есть хороший ярлык из этого. – TZHX

+0

Является ли ваш массив B построенным из A - скажем, выбирая из него или как A, так и B выбирается из родительского объекта - или он построен независимо? Если он построен по-другому, мы, возможно, должны проявлять терпимость к некоторой ошибке с плавающей запятой, что исключает некоторые удобные подходы. – DSM

+0

@TZHX спасибо за предложение :) –

ответ

0

Это версия с лучшей временной сложностью [O (п) в среднем по https://wiki.python.org/moin/TimeComplexity]:

import numpy as np 

def common_rows(A, B): 
    items = set(tuple(row) for row in B) 
    return np.array([row for row in A if tuple(row[:3]) in items]) 

n = 10000 
A = np.random.rand(n, 5) 
B = np.random.rand(n, 3) 

# Make some common rows 
B[123,:] = A[5775,:3] 
B[1443,:] = A[85,:3] 

print("-- Expected:") 
print(B[123]) 
print(B[1443]) 
print("-- Got:") 
print(common_rows(A, B)) 

Numpy не имеет структуру set данных, поэтому мы преобразуем здесь каждую строку в объект Python , Это несколько неэффективно, но должно быть быстрее для больших n.

+0

спасибо пв. но я думаю, что это будет работать только для массивов одинаковой формы. Для моего случая я возвращаю пустой массив. –

+0

@wormholespacetime: работает также для разных форм с незначительной модификацией: см. Обновление –

+0

Ничего себе ... это похоже на работу! Большое спасибо pv. :) –

1

Вы можете использовать набор логики:

Seta & SETB вернет все элементы в А, в только B:

a = set(list1) 
b = set(list2) 
c = a & b 

с теперь будет содержать спички!

Edit, так как я не видел Numpy ссылку, если искать документы вы можете найти метод, который вы ищете:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.intersect1d.html#numpy.intersect1d

+0

Спасибо добавил68 !! Я также попробую это сделать –

+0

hmmm ... Я думаю, что это действительно не помогает, поскольку я не могу найти, где расположены строки, чтобы выбрать элементы, которые я хочу в новом массиве. –

+0

Вы можете просто сохранить возвращаемые значения этого функция в другую переменную? c = np.insersect1d (a, b) – adds68

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