How to check if an array is multidimensional - python

I am trying to write a code to check if n is the maximum of the array A if it is return True if it isnt return False but I have two conditions if the value is a multidimentional or unidimentional I don't know how to write that:
if [A is unidimentional]:
maximum=A[0]
for i in range(A.shape[0]):
if max(A[i],maximum)==A[i]:
maximum=A[i]
if max(n,maximum)!=n:
return False
return True
else:
maximum=A[0][0]
for i in range(A.shape[0]):
for j in range(A.shape[1]):
if max(A[i][j],maximum)==A[i][j]:
maximum=A[i][j]
if max(n,maximum)!=n:
return False
return True
if someone knows how I can write that condition it would be very helpful Thanks

def is_multidimensional(A):
return A.ndim > 1

Try the following:
import numpy as np
my_array = np.array([[1,2,3],[4,5,6]])
d = len(my_array.shape)
print(d) # Output: 2
Now, you can test against d, if its value is 2, then your array is 2 dimensions.

If you just want to check whether an array is multidimensional, just check the length of the shape of the array
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
print len(arr.shape)
If that value is greater than 1, then your array is multidimensional
But if all you want to do is check whether n is equal to the largest value in the array, you dont need to manually implement that. np.amax will tell you that:
largest_element = np.amax(arr)
if n == largest_element:
return True
else:
return False

If the matrix is multidimensional then max will return a list.
Otherwise it will return an int.
if type(max(A))== list:
# do some stuff for handling multidimensional
else:
# do some stuff for handling unidimensional
Or you could use numpy in which case
np.max(A)
returns an int regardless of A's dimensions.
A =[[1,2,3,4],[1,4,5,6]]
max(A)
Out[57]: [1, 4, 5, 6]
np.max(A)
Out[64]: 6

Related

how to optimize this code and make it faster on python

determine whether all values of a certain range are used in the array and at the same time there are no values in the array that will not be in the range. For example, the range is [1,5], and the array is [1,2,3,4,5] - everything is correct. Or the range [1,5], and the array [1,2,1,2,3,3,4,5] - everything is also true.
the range is [1,5], and the array [0,2,2,3,3,4,5] is already incorrect since there is no 0 in the range, and there is also a 1 missing in the array
I did this, but it's slow with big values and terrible:
def func(segment, arr):
segment_arr = []
for i in range(segment[0], segment[1] + 1):
segment_arr.append(i)
arr_corr = True
if min(arr) != min(segment_arr) or max(arr) != max(segment_arr):
arr_corr = False
else:
for i in range(len(arr)):
if arr[i] in segment_arr:
for a in range(len(segment_arr)):
if segment_arr[a] in arr:
continue
else:
arr_corr = False
else:
arr_corr = False
return arr_corr
To test if every member of a list/array/range x is in another list/array y:
all(e in y for e in x)
to test if only members of a list/array/range x are in another list/array y:
all(e in x for e in y)
The speed of these operations depends on the container type. all short circuits, so it will be faster when the test fails. in is very fast on set but can be slow on lists. Creation of set is slow and can eliminate the gains from the speed of doing in on a set. If you are working with numpy arrays, it will be faster to use numpy's intersect.
This should do what you're asking. If it is too slow, you will need to optimize the types. At that point, you will probably need to edit the question to give some clear examples of when it is too slow and what your constraints are:
def func(segment, arr):
return all(e in segment for e in arr) and all(e in arr for e in segment)
def func(segment, arr):
return set(list(range(segment[0], segment[1]+1))) == set(arr)
Build a set from allowed values
If the resulting set has "full" length, all is correct.
left, right = [1, 5]
values = [0, 2, 3, 4, 5]
values_are_correct = (
len({i for i in values if left <= i <= right}) == (right - left) + 1
)

np.argmax to return -1 if all values in the input are the same

I want to use np.argmax but I want to get -1 (or any other number) when all the elements in the array input are the same or if there are multiple occurences of them. For example, a = np.array([2, 2, 2]) -> I want to get -1 instead of 0. Is there any alternative function?
I do not know of such a function, but you could always write it yourself, e.g. like this:
import numpy as np
def my_index(arr):
"""
Input: arr should be a NumPy array.
Return -1 if at least one number in arr occurs more than once.
Else return the index of the maximum number.
"""
flat = arr.ravel()
if len(np.unique(flat)) < len(flat):
return -1
return np.argmax(arr)

Compare and multiply elements in a list

I'm trying to write in an algorithm a function that:
Check if all elements in a list are different
Multiply all elements in the list, except the zeros
But I can't find a way to compare all elements in one list, do you have any idea ?
Thanks!
PS: I use arr = np.random.randint(10, size=a) to create a random list
EDIT:
More precisely, I'm trying to check if, in a numpy array to be more precise, all the elements are the same or different, if they are different, that it returns me True.
Also, once that done, multiply all elements in the array except the zeros
For example:
If I have an array [4,2,6,8,9,0], the algorithm tells returns me at first True because all elements are different, then it multiplies them 4*2*6*8*9 except the 0
To check if all elements in a list are different you can convert the list into a set which removes duplicates and compare the length of the set to the original list. If the length of the set is different than the length of the list, then there are duplicates.
x = np.random.randint(10, size=10)
len(set(x)) == len(x)
To multiply all values except 0 you can do list comprehension to remove the 0s and use np.prod to multiply the values in the new list.
np.prod([i for i in x if i != 0])
Example:
x = np.random.randint(10, size=10)
if len(set(x)) == len(x):
print(np.prod([i for i in x if i != 0]))
else:
print("array is not unique")
You can use numpy.unique.
Following code snippet checks if all elements in the array are unique (different from each other) and if so, it will multiply non-zero values with factor factor:
import numpy as np
factor = 5
if np.unique(arr).size == arr.size:
arr[arr != 0] = arr[arr != 0] * factor
You can use Collections to find the unique numbers. I have included a code that solves your problem.
import numpy as np
from collections import Counter
a = 5
arr = np.random.randint(10, size=a)
result = 1 #Variable that will store the product
flag = 0 #The counter
#Check if all the numbers are unique
for i in Counter(arr):
if Counter(arr)[i] > 1:
flag = 1
break
#Convert the dictionary into a list
l = [i for i in Counter(arr)]
#Return the product of all the numbers in the list except 0
if flag == 0:
for i in l:
if i != 0:
result = result * i
else:
print("The numbers are not unique")
Just for fun, here's a one-liner:
arr = np.array([1, 2, 3, 4, 0])
np.prod(arr[arr!=0]) if np.unique(arr).size == arr.size else False
>>> 24
If the array is [1, 2, 3, 4, 4] the result is False

Numpy: Truth comparison of multidimensional arrays

So I am writing a sudoku solver using a 9x9 array for the grid and a 9x9x9 array for its possibilities. Due to the backtracking algorithm I am using, I have to check whether the Sudoku is still valid, aka:
If there is a field that does not contain a number and has no possibilities left, return False.
So far I implemented that as follows:
for j in range(9):
for i in range(9):
if puzzle[j,i] == 0 and (solving[j,i] == 0).sum() == 9:
return False
return True
If the square at (j,i) contained, for example, the options 2, 3 and 7, the according possibility array would be:
solving[j,i] = array([0, 2, 3, 0, 0, 0, 7, 0, 0], dtype = int8)
I am trying to avoid such loops here and elsewhere in my solver. I tried this as follows:
solving[where(puzzle == 0)]
This returned an n x 9 array, where n is the amount of empty squares in my puzzle. I want the function to return False if any of the n arrays with shape 1x9 is exactly equal to
array([0,0,0,0,0,0,0,0,0], dtype = int8)
However, I did not have any success with various tries including .any() and .all() experiments. This is the latest code I was using:
def is_valid(self, puzzle, solving):
if (solving[py.where(puzzle == 0)].all() == 0).sum() > 0:
return False
return True
... which always returns False. What's the proper way to code this?
I think the following is the check you want to do:
np.all(puzzle | np.any(solving, axis=-1)
This returns True if all cells either have a value assigned (puzzle), or (|) have at least a non-zero entry in solving (np.any(solving, axis=-1)).

Dealing with multi-dimensional arrays when ndims not known in advance

I am working with data from netcdf files, with multi-dimensional variables, read into numpy arrays. I need to scan all values in all dimensions (axes in numpy) and alter some values. But, I don't know in advance the dimension of any given variable. At runtime I can, of course, get the ndims and shapes of the numpy array.
How can I program a loop thru all values without knowing the number of dimensions, or shapes in advance? If I knew a variable was exactly 2 dimensions, I would do
shp=myarray.shape
for i in range(shp[0]):
for j in range(shp[1]):
do_something(myarray[i][j])
You should look into ravel, nditer and ndindex.
# For the simple case
for value in np.nditer(a):
do_something_with(value)
# This is similar to above
for value in a.ravel():
do_something_with(value)
# Or if you need the index
for idx in np.ndindex(a.shape):
a[idx] = do_something_with(a[idx])
On an unrelated note, numpy arrays are indexed a[i, j] instead of a[i][j]. In python a[i, j] is equivalent to indexing with a tuple, ie a[(i, j)].
You can use the flat property of numpy arrays, which returns a generator on all values (no matter the shape).
For instance:
>>> A = np.array([[1,2,3],[4,5,6]])
>>> for x in A.flat:
... print x
1
2
3
4
5
6
You can also set the values in the same order they're returned, e.g. like this:
>>> A.flat[:] = [x / 2 if x % 2 == 0 else x for x in A.flat]
>>> A
array([[1, 1, 3],
[2, 5, 3]])
I am not sure the order in which flat returns the elements is guaranteed in any way (as it iterates through the elements as they are in memory, so depending on your array convention you are likely to have it always being the same, unless you are really doing it on purpose, but be careful...)
And this will work for any dimension.
** -- Edit -- **
To clarify what I meant by 'order not guaranteed', the order of elements returned by flat does not change, but I think it would be unwise to count on it for things like row1 = A.flat[:N], although it will work most of the time.
This might be the easiest with recursion:
a = numpy.array(range(30)).reshape(5, 3, 2)
def recursive_do_something(array):
if len(array.shape) == 1:
for obj in array:
do_something(obj)
else:
for subarray in array:
recursive_do_something(subarray)
recursive_do_something(a)
In case you want the indices:
a = numpy.array(range(30)).reshape(5, 3, 2)
def do_something(x, indices):
print(indices, x)
def recursive_do_something(array, indices=None):
indices = indices or []
if len(array.shape) == 1:
for obj in array:
do_something(obj, indices)
else:
for i, subarray in enumerate(array):
recursive_do_something(subarray, indices + [i])
recursive_do_something(a)
Look into Python's itertools module.
Python 2: http://docs.python.org/2/library/itertools.html#itertools.product
Python 3: http://docs.python.org/3.3/library/itertools.html#itertools.product
This will allow you to do something along the lines of
for lengths in product(shp[0], shp[1], ...):
do_something(myarray[lengths[0]][lengths[1]]

Categories

Resources