How to vectorize a simple for loop in Python/Numpy

numpy, python, scipy, vectorization

Solution

Probably the fastest way to find all matches is to sort both arrays and walk through them together, like this working example:

import numpy as np

def is_less(a, b):
    # this ugliness is needed because we want to compare lexicographically same as np.lexsort(), from the last column backward
    for i in range(len(a)-1, -1, -1):
        if a[i]<b[i]: return True
        elif a[i]>b[i]: return False
    return False

def is_equal(a, b):
    for i in range(len(a)):
        if a[i] != b[i]: return False
    return True

# lat1 = np.array(([48.78,47.45],[38.56,39.53]))
# lat2 = np.array(([7.78,5.45],[48.78,47.45],[7.56,5.53]))
lat1 = np.load('arr.npy')
lat2 = np.load('refarr.npy')

idx1 = np.lexsort( lat1.transpose() )
idx2 = np.lexsort( lat2.transpose() )
ii = 0
jj = 0
while ii < len(idx1) and jj < len(idx2):
    a = lat1[ idx1[ii] , : ]
    b = lat2[ idx2[jj] , : ]
    if is_equal( a, b ):
        # do stuff with match
        print "match found: lat1=%s lat2=%s %d and %d" % ( repr(a), repr(b), idx1[ii], idx2[jj] )
        ii += 1
        jj += 1
    elif is_less( a, b ):
        ii += 1
    else:
        jj += 1

This may not be perfectly pythonic (perhaps someone can think of a nicer implementation using generators or itertools?) but it is hard to imagine any method that relies on searching one point at a time beating this in speed.

Problem

I found dozens of examples how to vectorize for loops in Python/NumPy. Unfortunately, I don't get how I can reduce the computation time of my simple for loop using a vectorized form. Is it even possible in this case? ``` time = np.zeros(185000) lat1 = np.array(([48.78,47.45],[38.56,39.53],...)) # ~ 200000 rows lat2 = np.array(([7.78,5.45],[7.56,5.53],...)) # same number of rows as time for ii in np.arange(len(time)): pos = np.argwhere( (lat1[:,0]==lat2[ii,0]) and \ (lat1[:,1]==lat2[ii,1]) ) if pos.size: pos = int(pos) time[ii] = dtime[pos] ```

Original source