How can I fix this Index Error in python? - python

My code is as follows:
environment_rows = 3 #1
look_up_tables = [np.zeros((environment_rows, 20)) for _ in range(35)]
def get_starting_look_up_table(): #2
current_look_up_table = np.random.randint(35)
return current_look_up_table
def get_next_action(number_of_look_up_table,current_row_index,epsilon):
if np.random.random() < epsilon:
result=np.argmax(look_up_tables[number_of_look_up_table][current_row_index])
else: #choose a random action
result=np.random.randint(20)
return result
number_of_look_up_table = get_starting_look_up_table() #3
current_row_index = 0
epsilon = 0.9
action_index = get_next_action(current_row_index,number_of_look_up_table,epsilon)
In the first part, I produce the matrix related to look_up_tables, each of the arrays has three rows and twenty columns. We have a total of 35 of these arrays.
In the second part, using the 'get_starting_look_up_table' function, one of 35 is randomly selected. Also, by using the 'get next action' function, one of the 20 columns of the array selected by the previous function should be selected based on the largest value or randomly.
Finally, the functions are called in the third part, but I get the following error. When I run the line with the error separately, I don't have any problems. Thank you for guiding me in this regard.
IndexError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_28528/1385508929.py in <module>
2 current_row_index = 0
3
----> 4 action_index = get_next_action(current_row_index,number_of_look_up_table,epsilon)
5
6 reward = determine_rewards(number_of_look_up_table,current_row_index,action_index)
~\AppData\Local\Temp/ipykernel_28528/255015173.py in
get_next_action(number_of_look_up_table, current_row_index, epsilon)
9 def get_next_action(number_of_look_up_table,current_row_index,epsilon):
10 if np.random.random() < epsilon:
---> 11 return np.argmax(look_up_tables[number_of_look_up_table][current_row_index])
12 else: #choose a random action
13 return np.random.randint(20)
IndexError: index 27 is out of bounds for axis 0 with size 3

Your function call get_next_action(current_row_index, number_of_look_up_table, epsilon)
has the parameters in the wrong order. You switched current_row_index and number_of_look_up_table.
I think you want this:
action_index = get_next_action(number_of_look_up_table, current_row_index, epsilon)

Related

Find where the slope changes in my data as a parameter that can be easily indexed and extracted

I have the following data:
0.8340502011561366 0.8423491600218922
0.8513456021654467
0.8458192388553084
0.8440111276014195
0.8489589671423143
0.8738088120491972
0.8845129900705279
0.8988298998926688
0.924633964692693
0.9544790734065157
0.9908034431246875
1.0236430466543138
1.061619773027915
1.1050038249835414
1.1371449802490126
1.1921182610371368
1.2752207659022576
1.344047620255176
1.4198117350668353
1.507943067143741
1.622137968203745
1.6814098429502085
1.7646810054280595
1.8485457435775694
1.919591124757554
1.9843144220593145
2.030158014640226
2.018184122476175
2.0323466012624207
2.0179200409023874
2.0316932950853723
2.013683870089898
2.03010703506514
2.0216151623726977
2.038855467786505
2.0453923522466093
2.03759031642753
2.019424996752278
2.0441806106428606
2.0607521369415136
2.059310067318373
2.0661157975162485
2.053216429539864
2.0715123971225564
2.0580473413362075
2.055814512721712
2.0808278560688964
2.0601637029377113
2.0539429365156003
2.0609648613513754
2.0585135712612646
2.087674625814453
2.062482961966647
2.066476100210777
2.0568444178944967
2.0587903943282266
2.0506399365756396
The data plotted looks like:
I want to find the point where the slope changes in sign (I circled it in black. Should be around index 26):
I need to find this point of change for several hundred files. So far I tried the recommendation from this post:
Finding the point of a slope change as a free parameter- Python
I think since my data is a bit noisey I am not getting a smooth transition in the change of the slope.
This is the code I have tried so far:
import numpy as np
#load 1-D data file
file = str(sys.argv[1])
y = np.loadtxt(file)
#create X based on file length
x = np.linspace(1,len(y), num=len(y))
Find first derivative:
m = np.diff(y)/np.diff(x)
print(m)
#Find second derivative
b = np.diff(m)
print(b)
#find Index
index = 0
for difference in b:
index += 1
if difference < 0:
print(index, difference)
Since my data is noisey I am getting some negative values before the index I want. The index I want it to retrieve in this case is around 26 (which is where my data becomes constant). Does anyone have any suggestions on what I can do to solve this issue? Thank you!
A gradient approach is useless in this case because you don't care about velocities or vector fields. The knowledge of the gradient don't add extra information to locate the maximum value since the run are always positive hence will not effect the sign of the gradient. A method based entirly on raise is suggested.
Detect the indices for which the data are decreasing, find the difference between them and the location of the max value. Then by index manipulation you can find the value for which data has a maximum.
data = '0.8340502011561366 0.8423491600218922 0.8513456021654467 0.8458192388553084 0.8440111276014195 0.8489589671423143 0.8738088120491972 0.8845129900705279 0.8988298998926688 0.924633964692693 0.9544790734065157 0.9908034431246875 1.0236430466543138 1.061619773027915 1.1050038249835414 1.1371449802490126 1.1921182610371368 1.2752207659022576 1.344047620255176 1.4198117350668353 1.507943067143741 1.622137968203745 1.6814098429502085 1.7646810054280595 1.8485457435775694 1.919591124757554 1.9843144220593145 2.030158014640226 2.018184122476175 2.0323466012624207 2.0179200409023874 2.0316932950853723 2.013683870089898 2.03010703506514 2.0216151623726977 2.038855467786505 2.0453923522466093 2.03759031642753 2.019424996752278 2.0441806106428606 2.0607521369415136 2.059310067318373 2.0661157975162485 2.053216429539864 2.0715123971225564 2.0580473413362075 2.055814512721712 2.0808278560688964 2.0601637029377113 2.0539429365156003 2.0609648613513754 2.0585135712612646 2.087674625814453 2.062482961966647 2.066476100210777 2.0568444178944967 2.0587903943282266 2.0506399365756396'
data = data.split()
import numpy as np
a = np.array(data, dtype=float)
diff = np.diff(a)
neg_indeces = np.where(diff<0)[0]
neg_diff = np.diff(neg_indeces)
i_max_dif = np.where(neg_diff == neg_diff.max())[0][0] + 1
i_max = neg_indeces[i_max_dif] - 1 # because aise as a difference of two consecutive values
print(i_max, a[i_max])
Output
26 1.9843144220593145
Some details
print(neg_indeces) # all indeces of the negative values in the data
# [ 2 3 27 29 31 33 36 37 40 42 44 45 47 48 50 52 54 56]
print(neg_diff) # difference between such indices
# [ 1 24 2 2 2 3 1 3 2 2 1 2 1 2 2 2 2]
print(neg_diff.max()) # value with highest difference
# 24
print(i_max_dif) # location of the max index of neg_indeces -> 27
# 2
print(i_max) # index of the max of the origonal data
# 26
When the first derivative changes sign, that's when the slope sign changes. I don't think you need the second derivative, unless you want to determine the rate of change of the slope. You also aren't getting the second derivative. You're just getting the difference of the first derivative.
Also, you seem to be assigning arbitrary x values. If you're y-values represent points that are equally spaced apart, than it's ok, otherwise the derivative will be wrong.
Here's an example of how to get first and second der...
import numpy as np
x = np.linspace(1, 100, 1000)
y = np.cos(x)
# Find first derivative:
m = np.diff(y)/np.diff(x)
#Find second derivative
m2 = np.diff(m)/np.diff(x[:-1])
print(m)
print(m2)
# Get x-values where slope sign changes
c = len(m)
changes_index = []
for i in range(1, c):
prev_val = m[i-1]
val = m[i]
if prev_val < 0 and val > 0:
changes_index.append(i)
elif prev_val > 0 and val < 0:
changes_index.append(i)
for i in changes_index:
print(x[i])
notice I had to curtail the x values for the second der. That's because np.diff() returns one less point than the original input.

Error when trying to run code with a higher integer value (n > 20)

I'm a beginner programmer that's trying to write a program that requests an integer n within some defined limits and then computes certain mathematical functions and displays them in a formatted table.
At the moment I have the limits set so that (0 <= n <= 10000) but this might be the issue for now.
Here's my code:
#---------------------------Handling Exceptions------------------------------#
# this deals with the user typing in letters or numbers outside of the limit
# set
def inputNumber():
while True:
try:
userInput = int(input('Please enter an integer (0<=n<=10000): '))
while (userInput < 0) or (userInput > 10000):
print('This value is outside of the limits! Please try again.')
userInput = int(input('Please enter an integer: '))
except ValueError:
print('You did not enter a valid integer! Please try again.')
continue
else:
return userInput
#---------------------------end Handling Exceptions--------------------------#
#--------------------------Main Program Start--------------------------------#
import numpy as np # importing the numpy library
#inform the user what the program does
print('\nThis program asks the user to enter an integer value n and computes')
print(' sum(n), exp(n), n! and ln(n). It then displays the results in a table')
# set the variable n to user defined function
n = inputNumber()
# putting titles for each output column
title1, title2, title3, title4, title5 = 'n', 'sum(1..n)', 'exp(n)', 'n!', \
'ln(n!)'
# print in desired format
print('\n{0:>8}'.format(title1),
'{0:>10}'.format(title2),
'{0:>18}'.format(title3),
'{0:>20}'.format(title4),
'{0:>10}'.format(title5))
# setting up operators for sum and factorial functions using numpy:
def factorial(n): # function for factorial operator
if n == 1:
return n
elif n == 0:
return 1
else:
return n*factorial(n-1)
def nsum(n): # this is the summing function over n
if n == 0:
return 0
else:
return int(n*(n + 1)/2) # had to convert string to integer format
# reference: https://brilliant.org/wiki/sum-of-n-n2-or-n3/
# evaluate and print in for loop
for i in range(0, n+1):
n_int = 0 + i
sum_n = nsum(n_int)
exp_n = np.exp(n_int)
fact_n = factorial(n_int)
logfact_n = np.log(factorial(n_int))
print('{0:>8d}'.format(n_int),
'{0:>10d}'.format(sum_n),
'{0:>18.3f}'.format(exp_n),
'{0:>20d}'.format(fact_n),
'{0:>10.3f}'.format(logfact_n))
#--------------------------Main Program End----------------------------------#
The code runs fine and it is able to handle the exceptions but I get an AttributeError when I put n = 21.
AttributeError: 'int' object has no attribute 'log'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\pjjan\OneDrive\Documents\Python\forLoop3_19318421.py", line 79, in <module>
logfact_n = np.log(factorial(n_int))
TypeError: loop of ufunc does not support argument 0 of type int which has no callable log method
Here is the full output:
This program asks the user to enter an integer value n and computes
sum(n), exp(n), n! and ln(n). It then displays the results in a table
Please enter an integer (0<=n<=10000): 21
n sum(1..n) exp(n) n! ln(n!)
0 0 1.000 1 0.000
1 1 2.718 1 0.000
2 3 7.389 2 0.693
3 6 20.086 6 1.792
4 10 54.598 24 3.178
5 15 148.413 120 4.787
6 21 403.429 720 6.579
7 28 1096.633 5040 8.525
8 36 2980.958 40320 10.605
9 45 8103.084 362880 12.802
10 55 22026.466 3628800 15.104
11 66 59874.142 39916800 17.502
12 78 162754.791 479001600 19.987
13 91 442413.392 6227020800 22.552
14 105 1202604.284 87178291200 25.191
15 120 3269017.372 1307674368000 27.899
16 136 8886110.521 20922789888000 30.672
17 153 24154952.754 355687428096000 33.505
18 171 65659969.137 6402373705728000 36.395
19 190 178482300.963 121645100408832000 39.340
20 210 485165195.410 2432902008176640000 42.336
AttributeError: 'int' object has no attribute 'log'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\pjjan\OneDrive\Documents\Python\forLoop3_19318421.py", line 79, in <module>
logfact_n = np.log(factorial(n_int))
TypeError: loop of ufunc does not support argument 0 of type int which has no callable log method
I don't know how to resolve the issue and I'm using Python 3.8 for anyone wondering. I hope someone can help! Thank you and sorry for any trivial mistakes I've made in the code. I'm very much a beginner.
Factorial gets very big, very fast. After 20 (20! ~= 2e18), numpy switches to a different integer formulation that doesn't have a log method.
You can either use higher precision, or you can take advantage of the fact that multiplying log is the same as adding outside of it:
logfact_n += np.log(i)
(You'll have to fudge the first term since the log of 0 is undefined)
Proof:
np.cumsum(np.log(np.arange(20)+1))
Out[]: #same as your results
array([ 0. , 0.69314718, 1.79175947, 3.17805383, 4.78749174,
6.57925121, 8.52516136, 10.6046029 , 12.80182748, 15.10441257,
17.50230785, 19.9872145 , 22.55216385, 25.19122118, 27.89927138,
30.67186011, 33.50507345, 36.39544521, 39.33988419, 42.33561646])
The problem is that your 'int' grows so fast that produces an overflow. Try with long or double formats:
# evaluate and print in for loop
for i in range(0, n+1):
n_int = np.longdouble(0 + i)
sum_n = nsum(n_int)
exp_n = np.exp(n_int)
fact_n = factorial(n_int)
logfact_n = np.log(factorial(n_int))
print('{0:>8f}'.format(n_int),
'{0:>10f}'.format(sum_n),
'{0:>18.3f}'.format(exp_n),
'{0:>20f}'.format(fact_n),
'{0:>10.3f}'.format(logfact_n))

Iterating through txt file over interval; Python TypeError: 'int' object is not subscriptable

I have txt files filled with a column of time values and a column of potential (V) values. I am trying to record the V value every 1 hour (timestep) with t0 = 2 hours and tf = 12 hours. I have not seen this error before and do not know where it is coming from. Any help optimizing the code would be appreciated.
def bisection(array,value):
'''Given an ``array`` , and given a ``value`` , returns an index j such that ``value`` is between array[j]
and array[j+1]. ``array`` must be monotonic increasing. j=-1 or j=len(array) is returned
to indicate that ``value`` is out of range below and above respectively.'''
n = len(array)
if (value < array[0]):
return -1
elif (value > array[n-1]):
return n
jl = 0 # Initialize lower
ju = n-1 # and upper limits.
while (ju-jl > 1): # If we are not yet done,
jm=(ju+jl) >> 1 # compute a midpoint with a bitshift
if (value >= array[jm]):
jl=jm # and replace either the lower limit
else:
ju=jm # or the upper limit, as appropriate.
# Repeat until the test condition is satisfied.
if (value == array[0]): # edge cases at bottom
return 0
elif (value == array[n-1]): # and top
return n-1
else:
return array[jl],jl
def scatterBisect(txtfile,start,end,interval):
t_vals = txtfile[:,0]
V_vals = txtfile[:,1]
t_points = []
V_points = []
t = bisection(t_vals,start)[0]
while t <= end:
i = bisection(t_vals,t)[1]
V_points.append(V_vals[i])
t = bisection(t_vals,t + interval)[0]
t_points.append(t)
return t_points, V_points
x,y = scatterBisect(H_M_5a_purple,2,12,1)
plt.scatter(x,y)
plt.show()
Here is the full error traceback:
TypeError Traceback (most recent call last)
<ipython-input-33-1eff7c030470> in <module>()
17 return t_points, V_points
18
---> 19 x,y = scatterBisect(H_M_5a_purple,2,12,1)
20
21 plt.scatter(x,y)
<ipython-input-33-1eff7c030470> in scatterBisect(txtfile, start, end, interval)
11 i = bisection(t_vals,t)[1]
12 V_points.append(V_vals[i])
---> 13 t = bisection(t_vals,t + interval)[0]
14 t_points.append(t)
TypeError: 'int' object is not subscriptable

Question on multiplication in function in python

I am trying to create a simple function that returns multiplier output as shown below.
The question i want to ask is when print(times3), it does not gives a value but instead it shows
".multiplier at 0x00000236884B3558>" which I am unsure why. Is there a way to print the number instead?
Another question is since def multiplier(n) returns n*n, shouldn't it gives 5*5=25? Therefore if I were to print(times5(times3(2))), it should give me 25*81?
def make_multiplier_of(n):
def multiplier(n):
return n*n
return multiplier
# Multiplier of 3
times3 = make_multiplier_of(3)
print(times3)
# Multiplier of 5
times5 = make_multiplier_of(5)
# Output: 81
print(times3(9))
# Output: 9
print(times5(3)) #shouldn't it be 25?
# Output: 16 #shouldn't it be 81 x 25?
print(times5(times3(2)))
updated code:
def make_multiplier_of(n):
def multiplier(m):
return m*n
return multiplier
# Multiplier of 3
times3 = make_multiplier_of(3)
#trying to print out times3 value here but it doesnt work
times3.__closure__[0].cell_contents
[cell.cell_contents for cell in times3.__closure__]
# Multiplier of 5
times5 = make_multiplier_of(5)
# Output: 27
print(times3(9))
# Output: 15
print(times5(3)) #shouldn't it be 25?
# Output: 30
print(times5(times3(2)))
You need to use different variables for the parameters of the inner and outer functions.
def make_multiplier_of(m):
def multiplier(n):
return m*n
return multiplier
Your function is ignoring the argument to make_multiplier_of() because n only refers to the argument to multiplier().

IndexError When Iterating Through N-Dimensional Array

As mentioned in the title, I am getting an IndexError when iterating through a n-dimensional array. What I am trying to do with the code, is to set portions of the matrix to 0 and keep the rest of the data.
I also realize that selecting an element in a n-dimensional array should be array[row#][column#] but it is just a problem with my naming convention which I will fix later. However, the values are correct.
currentMatrix = np.array(ast.literal_eval(safety.iloc[i]), dtype=np.int)
currentMatrix.shape = (27,15)
tpHeight = int(df['touchH'].iloc[i])
tpWidth = int(df['touchW'].iloc[i])
fullRows = np.arange(15)
fullColumns = np.arange(27)
beforeAreaColumns = np.arange(df['touchX'].iloc[i] - 1, dtype=np.int)
afterAreaColumns = np.arange(df['touchX'].iloc[i] + tpWidth - 1, dtype=np.int)
beforeAreaRows = np.arange(df['touchY'].iloc[i] - 1, dtype=np.int)
afterAreaRows = np.arange(df['touchY'].iloc[i] + tpHeight - 1, dtype=np.int)
print beforeAreaColumns #returns [0 1 2 3 4 5] at i = 0
currentMatrix[beforeAreaColumns][fullRows] = 0
currentMatrix[afterAreaColumns][fullRows] = 0
currentMatrix[fullColumns][beforeAreaRows] = 0
currentMatrix[fullColumns][afterAreaRows] = 0
The error I receive is:
IndexError Traceback (most recent call last)
<ipython-input-114-342e7c1b89ae> in <module>()
26 print beforeAreaColumns
27
---> 28 currentMatrix[beforeAreaColumns][fullRows] = 0
29 currentMatrix[afterAreaColumns][fullRows] = 0
30 currentMatrix[fullColumns][beforeAreaRows] = 0
IndexError: index 6 is out of bounds for axis 0 with size 6
From my understanding, I am getting the error because the code tries to find an index in position 7 when there are only 6 positions. However, I am not sure why it tries index 6 when the array stops at index 5.
I tried changing the code so that it uses for loops, for example:
for beforeAreaColumn in beforeAreaColumns:
for fullRow in fullRows:
currentMatrix[beforeAreaColumn][fullRow] = 0
but I get the same error. The above code is written and run on Python 2.7.

Categories