Edna
Edna

Reputation: 5

Python - Cutting an array at a designated point based on value in row

I have a 300 x 4 matrix called X created by the odeint function. In the second column are y-values and I would like to cut the matrix when the y-value dips below 0. As a first step I was attempting to create a function that would read the second column and spit out the row number where the column first dips below 0.

    X = odeint(func, X0, t)

    Yval = X[:,1]

    def indexer():
        i = 0
        if Yval[i] > 0:
            i = i + 1
        if Yval[i] < 0:
            return i

Which is not working and conceptually I know this is wrong, I just couldn't think of another way to do this. Is there a way to cut out all the rows that contain and follow the first <0 y value?

This is my entire code:

    import numpy as np
    import math
    from scipy.integrate import odeint

    g = 9.8
    theta = (45 * math.pi)/180
    v0 = 10.0
    k = 0.3

    x0 = 0
    y0 = 0
    vx0 = v0*math.sin(theta)
    vy0 = v0*math.cos(theta)

    def func(i_state,time):
        f = np.zeros(4)
        f[0] = i_state[2]
        f[1] = i_state[3]
        f[2] = -k*(f[0]**2 + f[1]**2)**(.5)*f[0]
        f[3] = -g - k*(f[0]**2 + f[1]**2)**(.5)*f[1]
        return f

    X0 = [x0, y0, vx0, vy0]
    t0 = 0

    tf = 3
    timestep = 0.01

    nsteps = (tf - t0)/timestep
    t = np.linspace(t0, tf, num = nsteps)

    X = odeint(func, X0, t)

    Yval = X[:,1]

    def indexer():
        i = 0
        if Yval[i] > 0:
            i = i + 1
        if Yval[i] < 0:
            return i

Upvotes: 0

Views: 385

Answers (2)

Tom Myddeltyn
Tom Myddeltyn

Reputation: 1375

You could do something like this:

newVals = []
i = 0
while( i < len(X) and X[i][1] >= 0):
    newVals.append(X[i])
    i += 1

This would go through X and append values to the list newVals until you either reach the end of the list (i < len(X)) or you reach your condition (X[i][1] >= 0).

Upvotes: 0

Carlos Mermingas
Carlos Mermingas

Reputation: 3892

Maybe you could use the takewhile function from the itertools package:

from itertools import takewhile
first_elements = list(takewhile(lambda x: x[1] >= 0, X))

Where X is your matrix. I used x[1] in the lambda predicate to compare the numbers in the second column.

Here, first_elements will be the rows of the matrix before the first row that contains a value less than zero. You can use len(first_elements) to know what the cutoff point was.

I converted it to a list but you don't have to if you are just going to iterate through the result.

I hope this works.

Upvotes: 2

Related Questions