Not able to append arrays into a list - python

So I want to run this code to find a random element of a list containing numpy arrays with a certain condition
The conditions are that is for every element of arr1 not equal to arr2 it will append the element of that index of er and append it to lst:
import numpy as np
import random
arr1 = np.array([1,2,3,4])
arr2 = np.array([1,2,6,3])
arr = (arr1 == arr2)
er = np.array([[1,2],[-6,7],[4,7],[6,2]])
lst = []
for i in arr:
if i == False:
lst.append(er[i])
print(random.choice(lst))
But I don't know why its returning a empty list.Please help

arr is a boolean array, so in for loop i is True/False values (not an index)
for i in arr:
Change
for i in arr:
if i == False:
lst.append(er[i])
To:
for i, v in enumerate(arr): # retrieving index and value
if v == False: # test value
lst.append(er[i]) # use i to index into er

try this:
import numpy as np
import random
arr1 = np.array([1,2,3,4])
arr2 = np.array([1,2,6,3])
arr = (arr1 == arr2)
er = np.array([[1,2],[-6,7],[4,7],[6,2]])
lst = []
for i in range(len(arr1-1)):
if arr1[i] != arr2[i]:
lst.append(er[i])
print(random.choice(lst))

Related

How to combine two arrays for a specific index without concatenation?

I have two arrays that I want to merge to a new one but I need to insert the indices in specific places
array1 = np.arange(95,320,4)
array2 = np.arange(0,360,2)
For example.. array1[0] = 95, but I want this value to be in a new array between array2[47] which equals 94 and array2[48] that equals 96, and so on with the rest of the values inside array1.
Is this possible?
I think that you're looking for numpy.insert
array1 = np.arange(95,320,4)
array2 = np.arange(0,360,2)
for i, value in enumerate(array1):
index = i+48+i*2
array2 = np.insert(array2, index, array1[i])
It is not clear what you want exactly, but it might be the following:
So you have two arrays (arr1 and arr2):
import numpy as np
arr1 = np.arange(95, 320, 4)
arr2 = np.arange(0, 360, 2)
And you have two lists of indexes (idxs1 and idxs2) mapping between those arrays' elements and their index in the merged array:
n1, n2 = len(arr1), len(arr2)
n = n1 + n2
idxs = np.arange(n)
rng = np.random.default_rng()
rng.shuffle(idxs)
idxs1 = idxs[:n1]
idxs2 = idxs[n1:]
Then you can construct the merged array pretty easily as so:
merged = np.empty(n)
merged[idxs1] = arr1
merged[idxs2] = arr2
Let's check the properties I assumed you want to achieved:
for i in range(n1):
assert merged[idxs1[i]] == arr1[i]
for i in range(n2):
assert merged[idxs2[i]] == arr2[i]

How to split an array into multiple arrays based on a specific value in python

Consider I have an array of random values. In the array there is a value that is close to 0, but is not 0, that repeats consecutively at random places. What I want to do is to find these values and split the array into multiple arrays exactly at this place at the same time removing the repeating values. Restriction is that I cannot eliminate the value if it is not repeated more than twice consecutively.
For example:
array=np.array([-0.005,-0.004,0.00002,-0.003,0.004,0.00002,0.00002,0.00002,0.00002,
0.005,0.003,0.00002,0.0006,0.008,0.00002,0.00002,0.00002,
-0.003,0.006,0.007,0.00002,0.00002,0.00002])
minval=np.abs(array).min()
print(minval)
I find that 0.00002 is the value closest to 0, and therefore my aims is to obtain:
array1=([-0.005,-0.004,0.00002,-0.003,0.004],[0.005,0.003,0.00002,0.0006,0.008],[-0.003,0.006,0.007])
Is there a convenient way to do that in Python?
You can achieve that relatively easy with iterator:
import numpy as np
def split_by_min(arr):
equals = np.isclose(arr, np.abs(arr).min())
l = []
is_ready = False
for i in range(len(arr)):
if equals[i] and i < len(arr)-1 and equals[i+1]:
is_ready = True
elif not equals[i] and is_ready:
yield l
l = []
is_ready = False
if not is_ready:
l.append(arr[i])
yield l
arr = np.array([-0.005,-0.004,0.00002,-0.003,0.004,0.00002,0.00002,0.00002,
0.00002,0.005,0.003,0.00002,0.0006,0.008,0.00002,0.00002,
0.00002,-0.003,0.006,0.007,0.00002,0.00002,0.00002])
for l in split_by_min(arr):
print(l)
Output:
[-0.005, -0.004, 2e-05, -0.003, 0.004]
[0.005, 0.003, 2e-05, 0.0006, 0.008]
[-0.003, 0.006, 0.007]
You could do it like this:
import numpy as np
array=np.array([-0.005,-0.004,0.00002,-0.003,0.004,0.00002,0.00002,0.00002,0.00002,
0.005,0.003,0.00002,0.0006,0.008,0.00002,0.00002,0.00002,
-0.003,0.006,0.007,0.00002,0.00002,0.00002])
absArr = np.abs(array)
min_val=absArr.min()
idx = np.where(absArr == min_val)[0]
grad= idx[1:] - idx[:-1]
arrs = []
for l,u,g in zip(idx[:-1],idx[1:],grad):
print(l,u,g)
if g > 1:
arrs.append(array[l:u])
Then arrs has this content:
[[ 2.e-05 -3.e-03 4.e-03],
[2.e-05 5.e-03 3.e-03],
[2.e-05 6.e-04 8.e-03],
[ 2.e-05 -3.e-03 6.e-03 7.e-03]]

Cluster sizes in 2D numpy array?

I have a question similar to one that was already answered before, with slight modifications:
I have a 2-D numpy array with values -1,0,1. I want to find the cluster sizes of elements with values 1 or -1 (separately). Do you have any suggestions on how to do this?
Thanks!
This is my solution:
import numpy as np
import copy
arr = np.array([[1,1,-1,0,1],[1,1,0,1,1],[0,1,0,1,0],[-1,-1,1,0,1]])
print(arr)
col, row = arr.shape
mask_ = np.ma.make_mask(np.ones((col,row)))
cluster_size = {}
def find_neighbor(arr, mask, col_index, row_index):
index_holder = []
col, row = arr.shape
left = (col_index, row_index-1)
right = (col_index,row_index+1)
top = (col_index-1,row_index)
bottom = (col_index+1,row_index)
left_ = row_index-1>=0
right_ = (row_index+1)<row
top_ = (col_index-1)>=0
bottom_ = (col_index+1)<col
#print(list(zip([left,right,top,bottom],[left_,right_,top_,bottom_])))
for each in zip([left,right,top,bottom],[left_,right_,top_,bottom_]):
if each[-1]:
if arr[col_index,row_index]==arr[each[0][0],each[0][1]] and mask[each[0][0],each[0][1]]:
mask[each[0][0],each[0][1]] = False
index_holder.append(each[0])
return mask,index_holder
for i in range(col):
for j in range(row):
if mask_[i,j] == False:
pass
else:
value = arr[i,j]
mask_[i,j] = False
index_to_check = [(i,j)]
kk=1
while len(index_to_check)!=0:
index_to_check_deepcopy = copy.deepcopy(index_to_check)
for each in index_to_check:
mask_, temp_index = find_neighbor(arr,mask_,each[0],each[1])
index_to_check = index_to_check + temp_index
# print("check",each,temp_index,index_to_check)
kk+=len(temp_index)
for each in index_to_check_deepcopy:
del(index_to_check[index_to_check.index(each)])
if (value,kk) in cluster_size:
cluster_size[(value,kk)] = cluster_size[(value,kk)] + 1
else:
cluster_size[(value,kk)] = 1
print(cluster_size)
cluster_size is a dictionary, the key is a two member tuple (a,b), a give the value of the cluster (that's what you want to solve, right), b gives the counts of that value. The value for each key is the number of cluster.
Are you trying to count the number of 1 or -1 existing in the 2D array?
If so, then it is fairly easy. Say
ar = np.array([1, -1, 1, 0, -1])
If so,
n_1 = sum([1 for each in ar if each==1]);
n_m1 = sum([1 for each in ar if each==-1])

Numpy array condition to check if there is element with value +1 of current value

I would like to build something like this if statements into a numpy condition (for argwhere or similar).
for i, element in enumerate(array):
if array[i]+1 == array[i+1]:
return True
Is this possible or is looping through the array the only way?
You can use the np.roll function that shifts the array
import numpy as np
array+1 == np.roll(array, shift=-1)
This will return an array of boolean values.
You can use np.equal() function as well.
import numpy as np
a = [1,2,4,8,12,13]
x = np.array(a)
res = np.equal((x+1)[:-1], x[1:])
print(res)
Out:
[ True False False False True]
Note:
If you need speed, as it is usual the case, when we use numpy, it is worth to mention, that this methode is faster then np.roll(), what FBruzzesi proposed below and which is an elegant solution as well anyway:
import timeit
code1 = """
import numpy as np
a = [1,2,4,8,12,13]
x = np.array(a)
np.equal((x+1)[:-1], x[1:])
"""
elapsed_time1 = timeit.timeit(code1, number=10000)/100
print(elapsed_time1)
code2 = """
import numpy as np
a = [1,2,4,8,12,13]
x = np.array(a)
x+1 == np.roll(x, shift=-1)
"""
elapsed_time2 = timeit.timeit(code2, number=10000)/100
print(elapsed_time2)
Out:
0.00044608700000026147
0.0022752689999970244

"shape mismatch" error using numpy in python

I am trying to generate a random array of 0s and 1s, and I am getting the error: shape mismatch: objects cannot be broadcast to a single shape. The error seems to be occurring in the line randints = np.random.binomial(1,p,(n,n)). Here is the function:
import numpy as np
def rand(n,p):
'''Generates a random array subject to parameters p and N.'''
# Create an array using a random binomial with one trial and specified
# parameters.
randints = np.random.binomial(1,p,(n,n))
# Use nested while loops to go through each element of the array
# and assign True to 1 and False to 0.
i = 0
j = 0
rand = np.empty(shape = (n,n),dtype = bool)
while i < n:
while j < n:
if randints[i][j] == 0:
rand[i][j] = False
if randints[i][j] == 1:
rand[i][j] = True
j = j+1
i = i +1
j = 0
# Return the new array.
return rand
print rand
When I run it by itself, it returns <function rand at 0x1d00170>. What does this mean? How should I convert it to an array that can be worked with in other functions?
You needn't go through all of that,
randints = np.random.binomial(1,p,(n,n))
produces your array of 0 and 1 values,
rand_true_false = randints == 1
will produce another array, just with the 1s replaced with True and 0s with False.
Obviously, the answer by #danodonovan is the most Pythonic, but if you really want something more similar to your looping code. Here is an example that fixes the name conflicts and loops more simply.
import numpy as np
def my_rand(n,p):
'''Generates a random array subject to parameters p and N.'''
# Create an array using a random binomial with one trial and specified
# parameters.
randInts = np.random.binomial(1,p,(n,n))
# Use nested while loops to go through each element of the array
# and assign True to 1 and False to 0.
randBool = np.empty(shape = (n,n),dtype = bool)
for i in range(n):
for j in range(n):
if randInts[i][j] == 0:
randBool[i][j] = False
else:
randBool[i][j] = True
return randBool
newRand = my_rand(5,0.3)
print(newRand)

Categories

Resources