memo
memo

Reputation: 3734

Conditional maths operation on 2D numpy array checking on one dimension and doing different operations on diff dimensions

I have a 2D numpy array where column 0 is the pan rotation of a device and column 1 is the tilt rotation. Each row is a different fixture. I want to run the following logic on each row:

if(pantilt[0] > 90):
    pantilt[0] -=180
    pantilt[1] *= -1
elif pantilt[0] < -90:
    pantilt[0] += 180
    pantilt[1] *= -1

I understand basic conditional operations on 1D like myarray[condition] = something. But I can't extrapolate that into more dimensions.

Upvotes: 2

Views: 507

Answers (3)

Divakar
Divakar

Reputation: 221754

Inspired by this another related answer, one can use masking in three steps, instead of four steps as proposed in the other two solutions, like so -

import numpy as np

# Get mask correspindig to IF conditional statements in original code
mask_lt = pantilt[:,0]<-90
mask_gt = pantilt[:,0]>90

# Edit the first column as per the statements in original code
pantilt[:,0][mask_gt] -= 180
pantilt[:,0][mask_lt] += 180

# Edit the second column as per the statements in original code
pantilt[ mask_lt | mask_gt,1] *= -1

Runtime tests

Quick runtime tests to compare the three approaches listed so far -

In [530]: num_samples = 10000
     ...: org = np.random.randint(-180,180,(num_samples,2))
     ...: 

In [531]: pantilt = org.copy()

In [532]: %timeit hpaulj_mask4(pantilt)
10000 loops, best of 3: 27.7 µs per loop

In [533]: pantilt = org.copy()

In [534]: %timeit maxymoo_mask4(pantilt)
10000 loops, best of 3: 33.7 µs per loop

In [535]: pantilt = org.copy()

In [536]: %timeit mask3(pantilt) # three-step masking approach from this solution
10000 loops, best of 3: 22.1 µs per loop

Upvotes: 1

hpaulj
hpaulj

Reputation: 231738

I would calculate a mask, or boolean index, and use if for each column:

Construct a sample array:

pantilt=np.column_stack([np.linspace(-180,180,11),np.linspace(0,90,11)])

I = pantilt[:,0]>90
# J = pantilt[:,0]<-90 
pantilt[I,0] -= 180
pantilt[I,1] *= -1

I = pantilt[:,0]<-90  # could use J instead
pantilt[I,0] += 180
pantilt[I,1] *= -1

Before:

array([[-180.,    0.],
       [-144.,    9.],
       [-108.,   18.],
       [ -72.,   27.],
       [ -36.,   36.],
       [   0.,   45.],
       [  36.,   54.],
       [  72.,   63.],
       [ 108.,   72.],
       [ 144.,   81.],
       [ 180.,   90.]])

After:

array([[  0.,  -0.],
       [ 36.,  -9.],
       [ 72., -18.],
       [-72.,  27.],
       [-36.,  36.],
       [  0.,  45.],
       [ 36.,  54.],
       [ 72.,  63.],
       [-72., -72.],
       [-36., -81.],
       [  0., -90.]])

This would work just as well if the columns were separate 1d arrays.

Upvotes: 2

maxymoo
maxymoo

Reputation: 36555

How about this:

pantilt[:,0][pantilt[:,0]>90] -= 180
pantilt[:,1][pantilt[:,0]>90] *= -1
pantilt[:,0][pantilt[:,0]<-90] += 180
pantilt[:,1][pantilt[:,0]<-90] *= -1

Upvotes: 2

Related Questions