how to write an algorithm for finding specific values of a numpy array in python

痴心易碎 提交于 2021-01-29 17:18:55

问题


I have a serie of lines and want to extract some of them. This is the number of lines:

line_no= np.arange (17, 34)

These lines are arranged in two perependicular direction. I have shown them with bluw and red lines in the fig. I know where the direction is changing, it is called sep:

sep=25 # lines from 17 to 25 are blue and from 26 to end are red

Then, I have the number of the points that create the lines. I call them chunks, because each number can be chunk:

chunk_val=np.array([1,2,3,3,4])

This chunk_val says how lines are created. I need to extract specific line numbers which are highlighted by a blue circle in the fig. For the red lines the algorithm is simpler. chunk_val[0] is 1, it means I have no red line there. chunk_val[1] is 2, so I have one line and I want that line (26) because the previous chunk gave me no line. chunk_val[2] is 3, so I have two lines here and I want the one last line (28 out of 27 and 28), because previous chunk gave me one line. chunk_val[3] is 3, there are again two line but I want none of them because the number of created red lines in this chunk is equal to previous chunk. chunk_val[3] is 4, it creates three line and I want to export the number of last one (33 out of 31, 32 and 33) because it is creating one line more than previous chunk. If chunk_val[3] was 5, then I wanted to save the last two line.

For blue lines, that connect the chunks it is a little bit more complicated. chunk_val[0] is 1and chunk_val[1] is 2, it means there is one connecting line because first chunk_value defines how many lines can be there. Meanwhile, I want that line (17), because there is only one line. If there were more lines, I wanted to pick the last one. From chunk_val[1] to chunk_val[2] I have two lines and I want the last one (19 out of 18 and 19). Then, chunk_val[2] to chunk_val[3] there are three line and I want the last one (22 out of 20, 21 and 22). From chunk_value[3] to chunk_value[4] again there are three line and I want the last one (25 out of 23, 24 and 25). There is one very important note on how to pick these connecting (blue) lines: I want to start picking them from the first chunk_val untill where values of chunk_val change. In my example until the last number of chunk_val I see a change (chunk_val[-2] is 3 while chunk_val[-1] is 4). If chunk_val[-1] was also 3, then I wanted to stop picking the blue lines after going from chunk_val[1] to chunk_val[2] (I mean I only wanted to have 17 and 19). These are the idea of my algorithm but I have no idea to code it in python. In summary I want to have the following list of numbers:

[17, 26, 19, 28, 22, 25, 33]

In advance, I do appreciate any contribution.


回答1:


Upon reflection, there is a simpler solution to this problem (which can also be easily adapted for its twin problem):

import numpy as np
from scipy.ndimage.interpolation import shift

# Input data
line_no = np.arange (17, 34)
sep = 25  # lines from 17 to 25 are blue and from 26 to end are red
chunk_val = np.array([1,2,3,3,4])

# Blue candidates
blue_A = line_no[:np.where(line_no == sep)[0][0]+1]

# Red candidates
red_A = line_no[np.where(line_no == sep)[0][0]+1:]

# Select blue lines
blue_index = (chunk_val[:-1]).cumsum() - 1
blues = blue_A[blue_index]
blue_shift = (chunk_val[-1] - chunk_val)[:-1]
blues[blue_shift == 0] = 0  # set value of zero if no further jagged lines

# Select red lines
red_index = (chunk_val[1:] - 1).cumsum() - 1
reds = red_A[red_index]
red_shift = (chunk_val - shift(chunk_val, 1, cval=0))[1:]  # increments between successive series of red lines
reds[red_shift == 0] = 0  # set value of zero if no increment

# Merge blue lines and red lines
result = np.ravel(np.column_stack((blues, reds)))
result = result[result != 0]  # remove zeros
print(result)

Output:

[17 26 19 28 22 25 33]



回答2:


I agree with @sai's comment that this is probably best handled with some classes that represent the problem. Possibly a structure that represents the blue line to the right of the point and the red line up from the point. As I don't understand the problem I'm not sure what's best.

The code below works for the specific example in the question. I don't know whether it genuinely solves the question for different control lists or how to test it. Delete or comment out the two print statements when not required.

def specific_values( control, start = 0 ):
    cumulative = start
    blues = []  # List of lists of blues
    reds = []   # List of list of reds
    for i in control[ :-1 ]:  # The last item in control doesn't generate blues.
        temp=[]
        for j in range( cumulative, cumulative + i ):
            temp.append( j )
        blues.append(temp)
        cumulative += i
    print( blues )
    for ix, i in enumerate( control[ 1: ] ):  
        # The first item in the control doesn't generate reds.
        # The index is used to check whether the length of the red is less than 
        # the corresponding blue
        temp = [] 
        for j in range( cumulative, cumulative+i-1 ): 
            temp.append( j )
        while len(temp) < len( blues[ix] ):  
             temp.append( None )   # Pad the red with None to match the corresponding blue. 
        reds.append(temp) 
        cumulative += i-1
    print( reds )
    res = [] 
    for b_arr, r_arr in zip( blues, reds ): 
        res.append( b_arr[ -1 ] ) # Append last item in blues sub array to result
        res.append( r_arr[ -1 ] ) # Append last item in reds sub array to result
    return [ x for x in res if not x is None ]    # Filter out any Nones

control = [ 1, 2, 3, 3, 4 ]
specific_values( control, 17 )

There may be better ways to solve this but this represents the pattern I can see. What happens if a later control point is less than it's predecessor or if a control point is zero?



来源:https://stackoverflow.com/questions/65509793/how-to-write-an-algorithm-for-finding-specific-values-of-a-numpy-array-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!