How to use numpy to find connections between 2D and 3D arrays?

I have a numpy array of integer tuples of length 3 (x) and an numpy array of integer tuples of length 2 (y).

x = numpy.array([[3, 4, 5], [5, 12, 13], [6, 8, 10], [7, 24, 25]]) #first 4 elem
y = numpy.array([[3, 4], [4, 5], [3, 5], [5, 12]]) # first 4 elem

I am trying to compare the elements inside the array y: [a, b] and [b, c] and [a, c], which are subsets of the same element [a, b, c] in the array x. I call this union of functions. Below is my hard method to find a pool. This is not too good for my arrays that contain 200K minimal elements.

def union(x, y):
for intx in range (len(x)):
    cond1 = cond2 = cond3 = 0
    for inty in range (len(y)):
        if (y[inty][0] == x[intx][0] and y[inty][1] == x[intx][1]): #[a, b] & [a, b, c]
            print ("condition 1 passed")
            cond1 = 1
        if (y[inty][0] == x[intx][1] and y[inty][1] == x[intx][2]): #[b, c] & [a, b, c]
            print ("condition 2 passed")
            cond2 = 1
        if (y[inty][0] == x[intx][0] and y[inty][1] == x[intx][2]): #[a, c] & [a, b, c]
            print ("condition 3 passed")
            cond3 = 1
        if (cond1 & cond2 & cond3):
            print("union found with ", x[intx])
            cond1 = cond2 = cond3 = 0
return

>>> union(x,y)
condition 1 passed
condition 2 passed
condition 3 passed
union found with  [3 4 5]
condition 1 passed

UPDATE # 1: Example 1: this set of x and y does not have a union:

x = numpy.array([[21, 220, 221]])
y = numpy.array([[21, 220], [20, 21], [220,3021], [1220,3621], [60,221]])

UPDATE # 2: Example 2: this collection of x and y does not have a union:

x = numpy.array([[43, 924, 925]])
y = numpy.array([[43, 924], [924, 1643], [924,4307], [72, 925]])

Example 3: Here is a set of x and y that have a union [4, 8, 16].

x = numpy.array([[4, 8, 16], [8, 4, 16]])
y = numpy.array([[4, 8], [8, 16], [4, 16]])

Example 4: Here is the set of x and y that have a union [12, 14, 15].

x = numpy.array([[12, 13, 15], [12, 14, 15]])
y = numpy.array([[12, 14], [12, 13], [12, 15], [14, 15]])

. , x y [a, b, c],

x = numpy.array([[a, b, c], ...])
y = numpy.array([[a, b], [b, c], [a, c],...])

y

y = numpy.array([[...[b, c], [a, c], ... [a, b]])

, : ? , numpy.logical_and , x1 x2 . if isisisoint, . qaru.site/questions/1546480/...

+4
3

numpy_indexed ( : ) , :

from functools import reduce
import numpy_indexed as npi

def contains_union(x, y):
    """Returns an ndarray with a bool for each element in x, 
    indicating if it can be constructed as a union of elements in y"""
    idx = [[0, 1], [1, 2], [0, 2]]
    y = npi.as_index(y)   # not required, but a performance optimization
    return reduce(np.logical_and, (npi.in_(x[:, i], y) for i in idx))
+1

x, , :

import numpy as np

def union(x, y):
    # Create a boolean mask for the columns of "x"
    res = np.ones(x.shape[0], dtype=bool)
    # Mask containing the "x" rows that have one "partial match"
    res_tmp = np.zeros(x.shape[0], dtype=bool)
    # Walk through the axis-combinations
    # you could also use Divakars "(x[:,:2], x[:,::2], x[:,1:])" here.
    for cols in (x[:, [0, 1]], x[:, [1, 2]], x[:, [0, 2]]):
        # Check each row of y if it has a partial match
        for y_row in y:
            res_tmp |= (y_row == cols).all(axis=1)
        # Update the overall mask and then reset the partial match mask
        res &= res_tmp
        res_tmp[:] = 0
    return res

x = np.array([[3, 4, 5], [5, 12, 13], [6, 8, 10], [7, 24, 25]])
y = np.array([[3, 4], [4, 5], [3, 5], [5, 12]])
mask = union(x, y)
print(mask)     # array([ True, False, False, False], dtype=bool)
print(x[mask])  # array([[3, 4, 5]])

y:

y = np.array([[3, 4], [4, 5], [3, 5], [5, 12], [12, 13], [5, 13]])
mask = union(x, y)
print(x[mask])
# array([[ 3,  4,  5],
#        [ 5, 12, 13]])

, y_row == x[:, ax] . (, ) .

for y_row in y ( ), x y , , len(x) * len(y) ( , , , ).

+3

x , sqrt ( int 64?),

int (1e6) ,

import numpy

#rolled up all of the examples
x = numpy.array([[3, 4, 5], [5, 12, 13], [6, 8, 10], [7, 24, 25],
                [21, 220, 221],
                [43, 924, 925],
                [4, 8, 16], [8, 4, 16],
                [12, 13, 15], [12, 14, 15]]) #all examples

#and a numpy array of integer tuples of length 2:

y = numpy.array([[3, 4], [4, 5], [3, 5], [5, 12],
                [21, 220], [20, 21], [220,3021], [1220,3621], [60,221],
                [43, 924], [924, 1643], [924,4307], [72, 925],
                [4, 8], [8, 16], [4, 16],
                [12, 14], [12, 13], [12, 15], [14, 15]]) #all examples

#then make a couple of transform arrays

zx=numpy.array([[int(1e6), 1, 0],
                [0, int(1e6), 1],
                [int(1e6), 0, 1],
                ])
zy = numpy.array([[int(1e6)], [1]])


# and the magic is: np.intersect1d(zx @ x[ix], y @ zy)

# just to see part of what is being fed to intersect1d
print(zx @ x[0])
 [3000004 4000005 3000005]  

print(y[:4] @ zy)
[[3000004]
 [4000005]
 [3000005]
 [5000012]]


# if len of the intersection == 3 then you have your match

y_zy = y @ zy # only calc once
for ix in range(len(x)):
    matches = len(np.intersect1d(zx @ x[ix], y_zy))
    print(ix, matches, x[ix] if matches == 3 else '')
0 3 [3 4 5]
1 2 
2 0 
3 0 
4 1 
5 1 
6 3 [ 4  8 16]
7 2 
8 2 
9 3 [12 14 15]

I do not know the speed intersect1d, but according to the document it can be improved, if the flag unique=Truecan be set, it depends on your data

0
source

Source: https://habr.com/ru/post/1681075/


All Articles