问题
I am trying to code a function where it gives me the indexes of where either list_2
or list_3
crosses list_
. So it would give me the points of intersection if there are any in numpy code. I want to get the crosses in order, so the list of indexes have to be formatted so that it would give me a cross in order of list_2 cross, list_3 cross , list_2 cross
or list_3 cross, list_2 cross , list_3 cross
etc. So if a cross has happened it has to wait for the other array values to cross the list
before it can go through. I do not know how I can go through with this though I have tried using a numpy.where()
function and such, I am also using the pandas module so if it has a valid function for this I could use that too.
variables:
list_ = np.array([9887.89 9902.99 9902.99 9910.23 9920.79 9911.34 9920.01 9927.51 9932.3
9932.33 9928.87 9929.22 9929.22 9935.24 9935.24 9935.26 9935.26 9935.68
9935.68 9940.5 ])
list_2 = np.array([9935.26 9935.26 9935.68 9935.68 9940.5 9925.19 9925.19 9929.62 9929.65
9929.93 9932.55 9936.81 9936.84 9937.26 9932.55 9932.55 9932.55 9932.6
9932.6 9932.6])
list_3_ = np.array([9928.87 9929.22 9929.22 9935.24 9935.24 9935.26 9935.26 9935.68 9935.68
9940.5 9925.19 9925.19 9929.62 9929.65 9929.93 9932.55 9936.81 9936.84
9937.26 9932.55])
plot:
Expected Output:
List_2 cross at 5, List_3 cross at 10, List_2 cross at 14, List_3 cross at 15, List_2 cross at 18, List_3 cross at 19
回答1:
The crossing points or intersection indices between two series a
and b
are the indices i
where:
- either (ai < bi and ai+1 > bi+1) (
b
crossesa
from above) - or (ai > bi and ai+1 < bi+1) (
b
crossesa
from below) - or ai = bi (
a
andb
touch)
So we can get the indices by comparing the 'current' (i-th) and 'next' (i+1-th) values of each array.
def intersection_points(a, *others):
if a.ndim != 1 or any(other.shape != a.shape for other in others):
raise ValueError('The arrays must be single dimensional and the same length')
others = np.array(others)
indices = np.argwhere(
((a[:-1] < others[..., :-1]) & (a[1:] > others[..., 1:])) |
((a[:-1] > others[..., :-1]) & (a[1:] < others[..., 1:])) |
(a[:-1] == others[..., :-1]))
return indices[indices[:, 1].argsort()] # sort by i
a = np.array([9887.89, 9902.99, 9902.99, 9910.23, 9920.79, 9911.34, 9920.01, 9927.51, 9932.3, 9932.33, 9928.87, 9929.22, 9929.22, 9935.24, 9935.24, 9935.26, 9935.26, 9935.68, 9935.68, 9940.5])
b = np.array([9935.26, 9935.26, 9935.68, 9935.68, 9940.5, 9925.19, 9925.19, 9929.62, 9929.65, 9929.93, 9932.55, 9936.81, 9936.84, 9937.26, 9932.55, 9932.55, 9932.55, 9932.6, 9932.6, 9932.6])
c = np.array([9928.87, 9929.22, 9929.22, 9935.24, 9935.24, 9935.26, 9935.26, 9935.68, 9935.68, 9940.5, 9925.19, 9925.19, 9929.62, 9929.65, 9929.93, 9932.55, 9936.81, 9936.84, 9937.26, 9932.55])
print(intersection_points(a, b, c))
This returns an array of intersection points in this format:
[[ 0 7]
[ 0 9]
[ 1 9]
[ 1 11]
[ 1 12]
[ 0 13]
[ 1 15]
[ 1 18]]
meaning that b
(your list_2
) intersects with a
at indices 7, 9, 13, and c
(your list_3
) intersects with a
at indices 9, 11, 12, 15 and 18.
You seem to want the returned value to somehow alternate between intersections of the different lines and 'wait for the other array values to cross the list before it can go through'. It's not entirely clear what this would mean in every case but you can possibly do this by manipulating the result like this:
ip = intersection_points(a, b, c)
print(np.concatenate(([ip[0]], ip[1:][ip[:-1, 0] != ip[1:, 0]])))
returning
[[ 0, 7],
[ 1, 9],
[ 0, 13],
[ 1, 15]]
i.e. the first crossing is of b
at index 7, then c
at 9, then b
at 13, and finally c
at 15.
回答2:
This function converts arrays to lists and returns a list of tuples:
def find_cross(list_, list_2, list_3):
list_ = list_.tolist()
list_2 = list_2.tolist()
list_3 = list_3.tolist()
cross = []
i=0
for x,y in zip(list_2, list_3):
if x in list_:
cross.append((i, list_.index(x)))
if y in list_:
cross.append((i, list_.index(y)))
i+=1
return cross
来源:https://stackoverflow.com/questions/65925654/finding-the-point-of-intersection-of-3-numpy-arrays-python