How to add alternating trigonometric functions to an an array in Python?

Viewed 124

So I would like to add alternating Cos and Tan functions to an array in python with a given size. E.g. I have a numpy array of size (10,5) I want to add for each row, (Tan(a), Cos(a), Tan(a), Cos(a), Tan(a)). Could someone provide a hint as where to begin?

I tried setting a counter that used a while loop on the condition that the counter was less than 5 but this doesn't seem like it will work. Would really appreciate suggestions.

4 Answers

Solution

Since you asked for alternation, I thought of given a more generic answer with three types of alternation:

  • alternating row
  • alternating column you asked for this
  • alternating row and column (both): like a chess-board

I will use this dummy data in the subsequent examples: A, B, C

# dummy data
import numpy as np
angles = np.random.rand(5,4) * np.pi

A. Expected output: alternating row

[[tan, tan, tan, tan],
 [cos, cos, cos, cos],
 [tan, tan, tan, tan],
 [cos, cos, cos, cos],
 [tan, tan, tan, tan]]

Code:

# import numpy as np
a = np.zeros(angles.shape)
a[0::2, :] = np.tan(angles[0::2, :])
a[1::2, :] = np.cos(angles[1::2, :])

B. Expected output: alternating column

[[tan, cos, tan, cos],
 [tan, cos, tan, cos],
 [tan, cos, tan, cos],
 [tan, cos, tan, cos],
 [tan, cos, tan, cos]]

Code:

# import numpy as np
a = np.zeros(angles.shape)
a[:, 0::2] = np.tan(angles[:, 0::2])
a[:, 1::2] = np.cos(angles[:, 1::2])

C. Expected output: alternating row and column

[[tan, cos, tan, cos],
 [cos, tan, cos, tan],
 [tan, cos, tan, cos],
 [cos, tan, cos, tan],
 [tan, cos, tan, cos]]

Code:

# import numpy as np
a = np.zeros(angles.shape)
a[0::2, 0::2] = np.tan(angles([0::2, 0::2])) # tan: odd-row, odd-column
a[0::2, 1::2] = np.cos(angles([0::2, 1::2])) # cos: odd-row, even-column
a[1::2, 0::2] = np.cos(angles([1::2, 0::2])) # cos: even-row, odd-column
a[1::2, 1::2] = np.tan(angles([1::2, 1::2])) # tan: even-row, even-column

D. Benefit of using numpy vectorization for alternating rows

You can use the following custom-defined function: custom_trig_func(). Applying numpy functions to numpy arrays are faster if you can skip for loops. The more vectorized your code is, the quicker it will run. The approach here avoids using for loops and uses in-built vectorization of numpy.tan and numpy.cos.

custom_trig_func(angles)

However, if you just want the minimal lines of code to produce what the custom function does, use this:

# angles is your input ndarray
even_rows = (np.arange(angles.shape[0]) % 2 == 0)
out = np.tan(angles)
out[even_rows, :] = np.cos(angles[even_rows, :])
print(out.shape) # out is your expected output

Code

import numpy as np

def custom_trig_func(angles: np.ndarray, validate=False) -> np.ndarray:
    """Returns an array of type -> numpy.ndarray and shape -> angles.shape, with 
    - odd rows operated on by numpy.tan() and, 
    - even rows operated on by numpy.cos().
    """

    # determine odd and even row indices
    rows = np.arange(angles.shape[0])
    even_rows = (rows % 2 == 0)
    odd_rows = ~even_rows

    # create output array
    out = np.tan(angles)
    out[even_rows, :] = np.cos(angles[even_rows, :])

    if validate:
        assert np.all(out[odd_rows, :] == np.tan(angles[odd_rows, :])), "Validation error in applying TAN to odd rows"
        assert np.all(out[even_rows, :] == np.cos(angles[even_rows, :])), "Validation error in applying COS to even rows"

    return out

# dummy data
angles = np.random.rand(10,5) * np.pi
# apply custom function
custom_trig_func(angles=angles, validate=True)

Is this something u r looking for ?

import numpy as np
import math
x=np.array([x for x in range(50)]).reshape(10,5)
y=x.copy()
for i in range(x.shape[0]):
    y[i][0]=math.tan(x[i][0])
    y[i][1]=math.cos(x[i][1])
    y[i][2]=math.tan(x[i][2])
    y[i][3]=math.cos(x[i][3])
    y[i][4]=math.tan(x[i][4])
print(x)
print(y)




[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]
 [25 26 27 28 29]
 [30 31 32 33 34]
 [35 36 37 38 39]
 [40 41 42 43 44]
 [45 46 47 48 49]]

[[ 0  0 -2  0  1]
 [-3  0  0  0  0]
 [ 0  0  0  0  7]
 [ 0  0  3  0  0]
 [ 2  0  0  0 -2]
 [ 0  0 -3  0  0]
 [-6  0  0  0  0]
 [ 0  0  0  0  3]
 [-1  0  2  0  0]
 [ 1  0  0  0 -3]]

Something like this?

arr[:, ::2] = np.tan(arr[:, ::2])
arr[:, 1::2] = np.cos(arr[:, 1::2])

I'm being bold and assuming you're not very familiar with slicing notation and indexing in numpy, so you can consider going through the docs: Numpy Indexing.

You can zip through the transposed numpy array and the trigonometric functions (use a list comprehension to fit them with the array shape), my raw attempt:

import numpy as np

a = np.arange(50).reshape(10,5)
b = [([np.tan,np.cos]*(round(a.shape[1]//2+1)))[:-1] if a.shape[1] % 2 != 0 else [np.tan,np.cos]*(round(a.shape[1]/2))]
a = np.array([y(x) for x,y in zip(a.T,*b)])
Related