Issue obtaining minimum value of list/array - python

I'm having a weird issue, at least I can't explain the reason for this behaviour.
I generate a list of random values with the function rand_data as defined below. When I attempt to extract the minimum value using the min() function, it returns the whole list, which leads me to believe it is not a list but an array.
But if I attempt to use the .min() attribute it returns the error:
AttributeError: 'list' object has no attribute 'min'
What is happening here? Is x1 a list or an array?
Minimal working example:
import numpy as np
def rand_data():
return np.random.uniform(low=10., high=20., size=(10,))
# Generate data.
x1 = [rand_data() for i in range(1)]
print min(x1)
print x1.min()

You used a list comprehension:
x1 = [rand_data() for i in range(1)]
You now have a Python list object containing one result from rand_data().
Since rand_data() uses numpy.random.uniform() that means you have a list containing a numpy array.
Don't use a list comprehension here, it is clearly not what you wanted:
x1 = rand_data()

import numpy as np
def rand_data(num_elements):
# numpy returns always an array with a defined number
# of elements specified by the size parameter
return np.random.uniform(low=10., high=20., size=num_elements)
#rand_data will automatically generate the random data for you
# simply specifying the number of elements to generate
x1 = rand_data(10)
print('Minimum value for {0} is {1}'.format(x1, min(x1)))

Related

Strange comportement of list/array

I want to understand why the comportement of my array is like that:
import numpy as np
import math
n=10
P=np.array([[0]*n]*n)
P[2][2]=1 #It works as I want
for i in range(n):
for j in range(n):
P[i][j]=math.comb(n,j+1)*((i+1)/n)**(j+1)*(1-(i+1)/n)**(n-j-1)
print(math.comb(n,j+1)*((i+1)/n)**(j+1)*(1-(i+1)/n)**(n-j-1))
print(P)
I get as a result for P an array with only 0 except 1 for the (n,n) position but values printed are not 0.
I suppose it comes from the fact that I use [[0]*n]*n for my list with mutable/immutable variable because it works well when I use np.zeros() but I don't understand why it works when I set value manually (with P[2][2]=1 for example)
Thanks
The way you are creating the array is defaulting to an integer dtype because it uses the first value to determine the type if you don't explicitly set it. You can demonstrate this by trying to assign a float instead of an int with
P[2][2]=1 #It works as I want
P[2][2]=0.3 #It doesn't work
To use your approach you need to create an array with a dtype of float so values don't get clipped: P=np.array([[0.0]*n]*n) or P=np.array([[0]*n]*n, dtype=float).
This will produce an array of the expected values:
array([[3.87420489e-01, 1.93710245e-01, 5.73956280e-02, 1.11602610e-02,
1.48803480e-03, 1.37781000e-04, 8.74800000e-06, 3.64500000e-07,
9.00000000e-09, 1.00000000e-10],
[2.68435456e-01, 3.01989888e-01, 2.01326592e-01, 8.80803840e-02,
2.64241152e-02, 5.50502400e-03, 7.86432000e-04, 7.37280000e-05,
4.09600000e-06, 1.02400000e-07],
...

How to remove numbers in an array if it exists in another another

Here is my code so far. (Using NumPy for arrays)
avail_nums = np.array([1,2,3,4,5,6,7,8,9]) # initial available numbers
# print(avail_nums.shape[0])
# print(sudoku[spaces[x,1],spaces[x,2]]) # index of missing numbers in sudoku
print('\n')
# print(sudoku[spaces[x,1],:]) # rows of missing numbers
for i in range(sudoku[spaces[x,1],:].shape[0]): # Number of elements in the missing number row
for j in range(avail_nums.shape[0]): # Number of available numbers
if(sudoku[spaces[x,1],i] == avail_nums[j]):
avail_nums= np.delete(avail_nums,[j])
print(avail_nums)
A for loop cycles through all the elements in the 'sudoku row' and nested inside, another loop cycles through avail_nums. Every time there is a match (given by the if statement), that value is to be deleted from the avail_nums array until finally all the numbers in 'sudoku row' aren't in avail_nums.
I'm greeted with this error:
IndexError: index 8 is out of bounds for axis 0 with size 8
pointing to the line with the if statement.
Because avail_nums is shrinking, after the first deletion this happens. How can I resolve this issue?
When you are deleting items from the array, the array is getting smaller but your for loop does not know that because it is iterating over the original size of the array. So you are getting an out of bound error. So I would avoid using the for loop and deleting from the array I am iterating over.
My solution is to use a temporary array that contains allowed elements and then assign it to the original array name
temporary_array=list()
for element in array:
If element in another_array: # you can do this in Python
continue # ignore it
temporary_array.append(element)
array=temporary_array
the resulting array will have only the elements that do not exist in the another_array
You could also use list comprehension:
temporary_array = [ element for element in array if element not in another_array ]
array = temporary_array
Which is the same concept using fancy python syntax
Another option would be to use the builtin filter() which takes a filter function and an array and returns the filtered array. In the following I am using the lambda function notation, which is another nice Python syntax:
array = filter(lambda x: x not in another_array, array)
Since you are using numpy you should look for the numpy.extract() method here https://numpy.org/doc/stable/reference/generated/numpy.extract.html... for example using, numpy.where(), numpy.in1d() and numpy.extract() we could:
condition = numpy.where(numpy.in1d(np_array, np_another_array),False,True)
np_array = numpy.extract(condition, np_array)

setting an array element with a sequence error in python

I started studying python and I have a question for the program. I am writing
as the first step I thought of creating a big matrix and a big vectors where I will put some smaller vectors and smaller matrices. I created at random.
I have created a function that returns the max eigen values of those small matrices and save them in a vector. Also I created a function that basically does the multiplication of the transpose of my small vectors with the small matrices that I had randomly calculated. However when I try to pass the value of the multiplication, I get the following error
"setting an array element with a sequence."
import numpy as np
from scipy import linalg as lg
import math
N=5;
n=3;
Qs=np.zeros((n,N*n))
xs=np.zeros(n*N)
qs=np.zeros(n*N)
grads=np.zeros(N*n)
Lfi=np.zeros(N)
pis=np.zeros(N*n)
pi=np.zeros(N)
phat=np.zeros(N)
j=0;
gamma=np.zeros(N)
def gradient(Q,x) :
return x.transpose().dot(Q)
def eigen(Q):
val, vec = lg.eig(Q)
return np.amax(Q)
for i in range(0,N):
A = np.random.randint(10, size=(n,n))
Qs[0:n,j:j+n] += A
x = np.random.randint(10, size=(n))
qs[j:j+n] += x
x = np.random.randint(10, size=(n))
xs[j:j+n] += x
j = j+n
Lfi[i] = eigen(A)
grads[i] = gradient(A,x)
Why do I get the error for the gradient and not for example at the Lfi?
Your gradient function returns something else than what is expected by grads. From the error message I can tell that grads is numpy array which is not as forgiving as default python list. It has a type associated with it and it requires every element to be of that type.
e.g.
a = np.array([0] * 10)
print(type(a[0]))
this will tell you that the type of elements in this array is numpy.int64 (obviously there are many types and this is just a one of them). If you try to assign some value of a different type, python will try to coerce it to numpy.int64. But obviously, there is no sensible (general) way to coerce another array or matrix to a single number.
If you try
a[0] = [1, 2, 3]
then you will receive the error mentioned by you
ValueError: setting an array element with a sequence.
And why don't you receive the error when calling eigen function? Well, because it just returns a single value, not an array. np.amax(Q) returns a single value if you don't specify axis parameter which is set to None by default.

Avoiding an indexing error in Python while looping

Regardless of whether this is the most efficient way to structure this sorting algorithm in Python (it's not), my understandings of indexing requirements/the nature of the built-in 'min' function are failing to account for the following error in the following code:
Error:
builtins.IndexError: list index out of range
Here's the code:
#Create function to sort arrays with numeric entries in increasing order
def selection_sort(arr):
arruns = arr #pool of unsorted array values, initially the same as 'arr'
indmin = 0 #initialize arbitrary value for indmin.
#indmin is the index of the minimum value of the entries in arruns
for i in range(0,len(arr)):
if i > 0: #after the first looping cycle
del arruns[indmin] #remove the entry that has been properly sorted
#from the pool of unsorted values.
while arr[i] != min(arruns):
indmin = arruns.index(min(arruns)) #get index of min value in arruns
arr[i] = arruns[indmin]
#example case
x = [1,0,5,4] #simple array to be sorted
selection_sort(x)
print(x) #The expectation is: [0,1,4,5]
I've looked at a couple other index error examples and have not been able to attribute my problem to anything occurring while entering/exiting my while loop. I thought that my mapping of the sorting process was sound, but my code even fails on the simple array assigned to x above. Please help if able.
arr and arruns are the same lists. You are removing items from the list, decreasing its size, but leaving max value of i variable untouched.
Fix:
arruns = [] + arr
This will create new array for arruns

Importing just one value with numpy.genfromtxt

I would like to import just one value from a csv file. So far, I have been succesfull at using the skip_header and skip_footer options to seek out this element. It is a float value. One problem though, when I try to use this one element from my array, I get an error. Example:
import numpy as np
x = np.genfromtxt('junker.txt',skip_header=6,skip_footer=7)
print x
returns
array(10)
however
print x[0]
returns
TypeError: len() of unsized object
I just want to be able to use this value however I cannot because it's in a numpy array. Please help
a numpy array in that form is actually just a number. For example:
x = np.array([1])
Has a length of 1. However your array does not. Being just a number, you may utilize it right away! Example
x = np.array(3)
y = x + 3
print y
Will yield 3.
The length of x will yield an error because while this is an array, it is technically a zero dimensional array. Hence a length cannot be recovered from this variable.

Categories