[Numpy-discussion] Multiple Boolean Operations

Andrea Gavana andrea.gavana at gmail.com
Thu May 22 08:53:55 EDT 2008


Hi Francesc & All,

On Thu, May 22, 2008 at 1:04 PM, Francesc Alted wrote:
> I don't know if this is what you want, but you can get the boolean
> arrays separately, do the intersection and finally get the interesting
> values (by using fancy indexing) or coordinates (by using .nonzero()).
> Here it is an example:
>
> In [105]: a = numpy.arange(10,20)
>
> In [106]: c1=(a>=13)&(a<=17)
>
> In [107]: c2=(a>=14)&(a<=18)
>
> In [109]: all=c1&c2
>
> In [110]: a[all]
> Out[110]: array([14, 15, 16, 17])   # the values
>
> In [111]: all.nonzero()
> Out[111]: (array([4, 5, 6, 7]),)    # the coordinates

Thank you for this suggestion! I had forgotten  that this worked in
numpy :-( . I have written a couple of small functions to test your
method and my method (hopefully I did it correctly for both). On my
computer (Toshiba Notebook 2.00 GHz, Windows XP SP2, 1GB Ram, Python
2.5, numpy 1.0.3.1), your solution is about 30 times faster than mine
(implemented when I didn't know about multiple boolean operations in
numpy).

This is my code:

# Begin Code

import numpy
from timeit import Timer

# Number of cells in my original grid
nCells = 150000

# Define some constraints for X, Y, Z
xMin, xMax = 250.0, 700.0
yMin, yMax = 1000.0, 1900.0
zMin, zMax = 120.0, 300.0

# Generate random centroids for the cells
xCent = 1000.0*numpy.random.rand(nCells)
yCent = 2500.0*numpy.random.rand(nCells)
zCent = 400.0*numpy.random.rand(nCells)


def MultipleBoolean1():
    """ Andrea's solution, slow :-( ."""

    xReq_1 = numpy.nonzero(xCent >= xMin)
    xReq_2 = numpy.nonzero(xCent <= xMax)

    yReq_1 = numpy.nonzero(yCent >= yMin)
    yReq_2 = numpy.nonzero(yCent <= yMax)

    zReq_1 = numpy.nonzero(zCent >= zMin)
    zReq_2 = numpy.nonzero(zCent <= zMax)

    xReq = numpy.intersect1d_nu(xReq_1, xReq_2)
    yReq = numpy.intersect1d_nu(yReq_1, yReq_2)
    zReq = numpy.intersect1d_nu(zReq_1, zReq_2)

    xyReq = numpy.intersect1d_nu(xReq, yReq)
    xyzReq = numpy.intersect1d_nu(xyReq, zReq)


def MultipleBoolean2():
    """ Francesc's's solution, Much faster :-) ."""

    xyzReq = (xCent >= xMin) & (xCent <= xMax) &  \
             (yCent >= yMin) & (yCent <= yMax) &  \
             (zCent >= zMin) & (zCent <= zMax)

    xyzReq = numpy.nonzero(xyzReq)[0]


if __name__ == "__main__":

    trial = 10

    t = Timer("MultipleBoolean1()", "from __main__ import MultipleBoolean1")
    print "\n\nAndrea's Solution: %0.8g
Seconds/Trial"%(t.timeit(number=trial)/trial)

    t = Timer("MultipleBoolean2()", "from __main__ import MultipleBoolean2")
    print "Francesc's Solution: %0.8g
Seconds/Trial\n"%(t.timeit(number=trial)/trial)


# End Code


And I get this timing on my PC:

Andrea's Solution: 0.34946193 Seconds/Trial
Francesc's Solution: 0.011288139 Seconds/Trial

If I implemented everything correctly, this is an amazing improvement.
Thank you to everyone who provided suggestions, and thanks to the list
:-D

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/



More information about the NumPy-Discussion mailing list