0

I have written a code for SPC and I am attempting to highlight certain out of control runs. So I was wondering if there was a way to pull out n(in my case 7) amount of increasing elements in an array so I can index with with the color red when I go to plot them. This is what I attempted but I obviously get an indexing error.

import  numpy as np
import matplotlib.pyplot as plt

y = np.linspace(0,10,15) 
x = np.array([1,2,3,4,5,6,7,8,9,1,4,6,4,6,8])
col =[]
  
for i in range(len(x)):
    if x[i]<x[i+1] and x[i+1]<x[i+2] and x[i+2]<x[i+3] and x[i+3]<x[i+4] and x[i+4]<x[i+5] and x[i+5]<x[i+6] and x[i+6]<x[i+7]:
        col.append('red')  
    elif x[i]>x[i+1] and x[i+1]>x[i+2] and x[i+2]>x[i+3] and x[i+3]>x[i+4] and x[i+4]>x[i+5] and x[i+5]>x[i+6] and x[i+6]>x[i+7]:
        col.append('red')  
    else:
        col.append('blue') 
  
for i in range(len(x)):
      
    # plotting the corresponding x with y 
    # and respective color
    plt.scatter(y[i], x[i], c = col[i], s = 10,
                linewidth = 0)

Any help would be greatly appreciated!

4
  • The array x has 15 elements. In your first for loop, i will reach 8 at which point i+1 will be 15 which too large - hence the index error Commented Aug 5, 2021 at 19:46
  • "This is what I attempted but I obviously get an indexing error." If it's "obvious", then presumably you understand what is happening. Can you think of a mathematical rule that tells you the greatest value of i that will still avoid the indexing error? What happened when you tried using that rule to fix the for loop? Commented Aug 7, 2021 at 7:27
  • Please also see stackoverflow.com/questions/6822725/… ; if I understand correctly what you want to you, you may find it helps you write a more elegant solution. (Hint: if you wanted to check if an entire list were in ascending order, could you do that? Without knowing how many elements there are? You don't actually need to do any element-wise comparison yourself for that, actually. Hint 2: if the elements are in ascending order, you could say that they are sorted, right? So...) Commented Aug 7, 2021 at 7:28
  • @KarlKnechtel I ended up using a different solution to the two posted even though both were fantastic. My collaborators preferred the use of data frames which allowed for more possible solutions. I ended up creating a parallel data frame to store when the index is out of order. Thank you for your comments Commented Aug 18, 2021 at 17:05

2 Answers 2

0

As Andy said in his comment you get the index error because at i=8 you get to 15 which is the length of x.

Either you only loop over len(x)-7 and just repeat the last entry in col 7 times or you could do something like this:

import  numpy as np
import matplotlib.pyplot as plt

y = np.linspace(0,10,20)
x = np.array([1,2,3,4,5,6,1,2,3,1,0,-1,-2,-3,-4,-5,-6,4,5])
col =[]

diff = np.diff(x) # get diff to see if x inc + or dec - // len(x)-1
diff_sign = np.diff(np.sign(diff)) # get difference of the signs to get either 1 (true) or 0 (false) // len(x)-2
zero_crossings = np.where(diff_sign)[0] + 2 # get indices (-2 from len(x)-2) where a zero crossing occures
diff_zero_crossings = np.diff(np.concatenate([[0],zero_crossings,[len(x)]])) # get how long the periods are till next zero crossing

for i in diff_zero_crossings:
    if i >= 6:
        for _ in range(i):
            col.append("r")
    else:
        for _ in range(i):
            col.append("b")

for i in range(len(x)):

    # plotting the corresponding x with y
    # and respective color
    plt.scatter(y[i], x[i], c = col[i], s = 10,
            linewidth = 0)

plt.show()
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much! This is a very nice solution to the problem! I found a different solution involving data frames. I will also post this solution once I personally understand it better!
0

To determine if all integer elements of a list are ascending, you could do this:-

def ascending(arr):
    _rv = True
    for i in range(len(arr) - 1):
        if arr[i + 1] <= arr[i]:
            _rv = False
            break
    return _rv


a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 10, 11, 12, 13, 14, 16]
a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16]

print(ascending(a1))
print(ascending(a2))

If you want to limit the sequence of ascending values then you could just use nested loops. It may look inelegant but it's surprisingly efficient and much simpler than bringing dataframes into the mix:-

def ascending(arr, seq):
    for i in range(len(arr) - seq + 1):
        state = True
        for j in range(i, i + seq - 1):
            if arr[j] >= arr[j + 1]:
                state = False
                break
        if state:
            return True
    return False


a1 = [100, 99, 98, 6, 7, 8, 10, 11, 12, 13, 14, 13]
a2 = [9, 8, 7, 6, 5, 4, 3, 2, 1]

print(ascending(a1, 7))
print(ascending(a2, 7))

2 Comments

Hello, Thank you for your response. I'm uninterested in seeing if the entire list is increasing just if there is a run of 7 consecutive elements are increasing. I've found some code that uses dataframes to accomplish this, but I don't quite understand it. I will post once I get some clarity. Thank you so much again!
that is absolutely fabulous!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.