Related
I am able to generate the desired output but i need 10 of them and each list has to be unicue. The best solution i thought of was to create a 2nd function, generate a emty list and populate each element with list from 1st function. The output i got so far is x amount of lists but they are not unique and python gives me error when i try to call on the first function inside the 2nd one.
import random
numbers = list(range(1, 35))
out = []
final = []
print(numbers) # to see all numbers
# returns 7 unique pop'd numbers from list 'numbers' and appends them to list 'out'
def do():
for x in range(7):
out.append(numbers.pop(random.randrange(len(numbers))))
print(sorted(out))
# In other words i want to print output from function do() 10 times but each item in list has to be unique, not the lists themself
def do_ten():
for x in range(10):
final.append(out)
# do() python doesnt like this call
print(sorted(final))
do_ten()
This generates a specific amount of lists, in a list, which contain random numbers from 1 to 100, you can use l and n to control the amount of lists and numbers respectively.
import random
l, n = 3, 5 # The amount of lists and numbers respectively.
lis = [[i for i in random.sample(range(1, 35), n)] for group in range(l)]
print(lis)
Random Output:
[[16, 11, 17, 13, 9], [26, 6, 16, 29, 24], [24, 2, 4, 1, 20]]
You are popping 10 times 7 numbers from a list containing 34 elements (from 1 to 34). This is not possible. You need to have at least 70 elements in your list numbers(for example, from 0 to 69).
This is a solution that should work, based on the code you've already written:
import random
numbers = list(range(0, 70))
final = []
print(numbers) # to see all numbers
# returns a list of 7 unique popped numbers from list 'numbers'
def do():
out = []
for x in range(7):
l = len(numbers)
r = random.randrange(l)
t = numbers.pop(r)
out.append(t)
return out
# Call 10 times do() and add the returned list to 'final'
def do_ten():
for x in range(10):
out = do() # Get result from do()
final.append(out) # Add it to 'final'
do_ten()
print(final)
Does it help:
num_lists = 10
len_list = 10
[list(np.random.randint(1,11,len_list)) for _ in range(num_lists)]
As some people may have different definitin of "uniqueness", you may try:
source_list = range(0, num_lists*len_list,1)
[list(np.random.choice(source_list, len_list, replace=False)) for _ in range(num_lists)]
Pulling 7 of 34 numbers from your numberrange without repeats can be done using random.sample - to ensure you do not get duplicate lists, you can add a tuple of the list to a set and your final result and only add to final if this tuple is not yet in the set:
import random
numbers = range(1, 35) # 1...34
final = []
chosen = set()
while len(final) < 10:
# replace popping numbers with random.sample
one_list = random.sample(numbers, k=7) # 7 numbers out of 34 - no repeats
# create a tuple of this list and only add to final if not yet added
t = tuple(one_list)
if t not in chosen:
chosen.add(t)
final.append(one_list)
print (final)
Output:
[[1, 5, 10, 26, 14, 33, 6],
[3, 11, 1, 30, 7, 21, 18],
[24, 23, 28, 2, 13, 18, 1],
[4, 25, 32, 15, 22, 8, 27],
[32, 9, 10, 16, 17, 26, 12],
[34, 32, 10, 26, 16, 21, 20],
[6, 34, 22, 11, 26, 12, 5],
[29, 17, 25, 15, 3, 6, 5],
[24, 8, 31, 28, 17, 12, 15],
[6, 19, 11, 22, 30, 33, 15]]
If you dont need unique resulting lists, you can simplify this to a one-liner but it might have dupes inside:
final = [random.sample(range(1,11),k=7) for _ in range(10)]
I am using python-3.x and I would like to check if one of the numpy array rows in my_array_3 exists in the dictionary dic_t by trying the following way:
my_array_3[2] in dic_t.values()
but I get this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Also, I am trying to append this numpy array row to the dictionary under the key "array_1" by trying the following way:
dic_t["array_1"].append(my_array_3[2])
but I get this error:
AttributeError: 'numpy.ndarray' object has no attribute 'append'
I am not sure where the problem is and how to solve it since I tried different ways.
the full code is:
import numpy as np
# my first array
my_array_1 = np.array([[1 , 2, 3],
[32, 42, 11],
[9, 21, 22],
[9, 21, 22],
[9, 21, 22],
[32, 42, 11],
[1 , 2, 3]])
# my second array
my_array_2 = np.array([[23],[33],[45],[45],[45], [33], [23]])
# here I want to find the unique values index from my_array_1
_, my_array_1_indx = np.unique(my_array_1, return_index=True, axis=0)
# here I want to returen the unique values sorted from my_array_1
my_array_1_uniq = (my_array_1[np.sort(my_array_1_indx)])
# here I want to returen the unique values sorted from my_array_2 based on the my_array_1_indx
my_array_2_uniq = (my_array_2[np.sort(my_array_1_indx)])
#save the result to dictionary
dic_t= {"array_1": my_array_1_uniq,
"array_2": my_array_2_uniq}
my_array_3 = np.array([[23 , 4, 2],
[32, 42, 11],
[54, 1, 9],
[9, 21, 22],
[9, 21, 22],
[34, 67, 77],
[1 , 2, 3]])
# now I want to check if one of the rows in my_array_3 exists in the dictionary dic_t
for i in range (len(my_array_3)):
# here the first error ******
if my_array_3[i] in dic_t.values():
print ( my_array_3[i], " deleted")
my_array_3 = np.delete(my_array_3, (i), axis=0)
else:
print ( my_array_3[i], " added")
# here the second error ******
dic_t["array_1"].append(my_array_3[i])
Here is a working answer with two modifications:
First, you are checking for occurrence of a 1-d array in a list of arrays. This can be done using any and all as explained here
Second, you need to use vstack to insert/append a row to your array.
for i in range (len(my_array_3)):
if any((my_array_3[i] == j).all() for j in dic_t.values()):
print ( my_array_3[i], " deleted")
my_array_3 = np.delete(my_array_3, (i), axis=0)
else:
print ( my_array_3[i], " added")
dic_t["array_1"] = np.vstack((dic_t["array_1"], my_array_3[i]))
# [23 4 2] added
# [32 42 11] added
# [54 1 9] added
# [ 9 21 22] added
# [ 9 21 22] added
# [34 67 77] added
# [1 2 3] added
This the final solution if someone needs it (Thanks to #Sheldore)
# import numpy
import numpy as np
# my first array
my_array_1 = np.array([[1 , 2, 3],
[32, 42, 11],
[9, 21, 22],
[9, 21, 22],
[9, 21, 22],
[32, 42, 11],
[1 , 2, 3]])
# my second array
my_array_2 = np.array([[23],[33],[45],[45],[45], [33], [23]])
# here I want to find the unique values index from my_array_1
_, my_array_1_indx = np.unique(my_array_1, return_index=True, axis=0)
# here I want to returen the unique values sorted from my_array_1
my_array_1_uniq = (my_array_1[np.sort(my_array_1_indx)])
# here I want to returen the unique values sorted from my_array_2 based on the my_array_1_indx
my_array_2_uniq = (my_array_2[np.sort(my_array_1_indx)])
#save the result to dictionary
dic_t= {"array_1": my_array_1_uniq,
"array_2": my_array_2_uniq}
my_array_3 = np.array([[23 , 4, 2],
[32, 42, 11],
[54, 1, 9],
[9, 21, 22],
[9, 21, 22],
[34, 67, 77],
[1 , 2, 3]])
i=0
while i < len(my_array_3):
print ("\n *****************************************************", i)
if any((my_array_3[i] == j).all() for j in dic_t["array_1"]):
# print (my_array_3[i])
# print ( my_array_3[i], " deleted")
my_array_3 = np.delete(my_array_3, (i), axis=0)
print (" deleted")
# print (" lingh :", lingh)
else:
print ( my_array_3[i], " added")
dic_t["array_1"] = np.vstack((dic_t["array_1"], my_array_3[i]))
i+=1
Result :
***************************************************** 0
[23 4 2] added
***************************************************** 1
deleted
***************************************************** 1
[54 1 9] added
***************************************************** 2
deleted
***************************************************** 2
deleted
***************************************************** 2
[34 67 77] added
***************************************************** 3
deleted
This is a follow up on this question.
From a 2d array, create another 2d array composed of randomly selected values from original array (values not shared among rows) without using a loop
I am looking for a way to create a 2D array whose rows are randomly selected unique values (non-repeating) from another row, without using a loop.
Here is a way to do it With using a loop.
pool = np.random.randint(0, 30, size=[4,5])
seln = np.empty([4,3], int)
for i in range(0, pool.shape[0]):
seln[i] =np.random.choice(pool[i], 3, replace=False)
print('pool = ', pool)
print('seln = ', seln)
>pool = [[ 1 11 29 4 13]
[29 1 2 3 24]
[ 0 25 17 2 14]
[20 22 18 9 29]]
seln = [[ 8 12 0]
[ 4 19 13]
[ 8 15 24]
[12 12 19]]
Here is a method that does not uses a loop, however, it can select the same value multiple times in each row.
pool = np.random.randint(0, 30, size=[4,5])
print(pool)
array([[ 4, 18, 0, 15, 9],
[ 0, 9, 21, 26, 9],
[16, 28, 11, 19, 24],
[20, 6, 13, 2, 27]])
# New array shape
new_shape = (pool.shape[0],3)
# Indices where to randomly choose from
ix = np.random.choice(pool.shape[1], new_shape)
array([[0, 3, 3],
[1, 1, 4],
[2, 4, 4],
[1, 2, 1]])
ixs = (ix.T + range(0,np.prod(pool.shape),pool.shape[1])).T
array([[ 0, 3, 3],
[ 6, 6, 9],
[12, 14, 14],
[16, 17, 16]])
pool.flatten()[ixs].reshape(new_shape)
array([[ 4, 15, 15],
[ 9, 9, 9],
[11, 24, 24],
[ 6, 13, 6]])
I am looking for a method that does not use a loop, and if a particular value from a row is selected, that value can Not be selected again.
Here is a way without explicit looping. However, it requires generating an array of random numbers of the size of the original array. That said, the generation is done using compiled code so it should be pretty fast. It can fail if you happen to generate two identical numbers, but the chance of that happening is essentially zero.
m,n = 4,5
pool = np.random.randint(0, 30, size=[m,n])
new_width = 3
mask = np.argsort(np.random.rand(m,n))<new_width
pool[mask].reshape(m,3)
How it works:
We generate a random array of floats, and argsort it. By default, when artsort is applied to a 2d array it is applied along axis 1 so the value of the i,j entry of the argsorted list is what place the j-th entry of the i-th row would appear if you sorted the i-th row.
We then find all the values in this array where the entries whose values are less than new_width. Each row contains the numbers 0,...,n-1 in a random order, so exactly new_width of them will be less than new_width. This means each row of mask will have exactly new_width number of entries which are True, and the rest will be False (when you use a boolean operator between a ndarray and a scalar it applies it component-wise).
Finally, the boolean mask is applied to the original data to grab new_width many entries from each row.
You could also use np.vectorize for your loop solution, although that is just shorthand for a loop.
I'm not able understand what to do here. Can someone help.
I've a few lists:
array = [7,8,2,3,4,10,5,6,7,10,8,9,10,4,5,12,13,14,1,2,15,16,17]
slice = [2, 4, 6, 8, 10, 12, 15, 17, 20, 22]
intervals = [12, 17, 22]
output = []
intermediate = []
slice is a list of indices I need to get from slicing array. interval is a list of indices used to stop the slicing when slice[i] is interval[j] where i and j are looping variables.
I need to form a list of lists from array based on slice and intervals based on the condition that when slice[i] is not interval[j]
intermediate =intermediate + array[slice[i]:slice[i+1]+1]
here in my case:
when slice[i] and interval[j] are equal for value 12. So I need to form a list of lists from array
intermediate = array[slice[0]:slice[0+1]+1] + array[slice[2]:slice[2+1]+1] + array[slice[4]:slice[4+1]+1]
which is
intermediate = array[2:(4+1)] + array[6:(8+1)] + array[10:(12+1)]
and when slice[i] is interval[j] output = output + intermediate and the slicing is continued.
output = output + [intermediate]
which is
output = output + [array[2:(4+1)] + array[6:(8+1)] + array[10:(12+1)]]
now the next value in interval is 17 so till we have 17 in slice we form another list from array[slice[6]:slice[6+1]+1] and add this to the output. This continues.
The final output should be:
output = [array[slice[0]:slice[0+1]+1] + array[slice[2]:slice[2+1]+1] + array[slice[4]:slice[4+1]+1] , array[slice[6]:slice[6+1]+1], array[slice[8]:slice[8+1]+1]]
which is
output = [[2, 3, 4, 5, 6, 7, 8, 9, 10], [12, 13, 14], [15, 16, 17]]
A straightforward solution:
array_ = [7,8,2,3,4,10,5,6,7,10,8,9,10,4,5,12,13,14,1,2,15,16,17]
slice_ = [2, 4, 6, 8, 10, 12, 15, 17, 20, 22]
intervals = [12, 17, 22]
output = []
intermediate = []
for i in range(0, len(slice_), 2):
intermediate.extend(array_[slice_[i]:slice_[i+1]+1])
if slice_[i+1] in intervals:
output.append(intermediate)
intermediate = []
print output
# [[2, 3, 4, 5, 6, 7, 8, 9, 10], [12, 13, 14], [15, 16, 17]]
I have changed some variable names to avoid conflicts.
On large data, you may convert intervals to a set.
Here is a recursive solution which goes through the index once and dynamically check if the index is within the intervals and append the sliced results to a list accordingly:
def slicing(array, index, stops, sliced):
# if the length of index is smaller than two, stop
if len(index) < 2:
return
# if the first element of the index in the intervals, create a new list in the result
# accordingly and move one index forward
elif index[0] in stops:
if len(index) >= 3:
sliced += [[]]
slicing(array, index[1:], stops, sliced)
# if the second element of the index is in the intervals, append the slice to the last
# element of the list, create a new sublist and move two indexes forward accordingly
elif index[1] in stops:
sliced[-1] += array[index[0]:(index[1]+1)]
if len(index) >= 4:
sliced += [[]]
slicing(array, index[2:], stops, sliced)
# append the new slice to the last element of the result list and move two index
# forward if none of the above conditions satisfied:
else:
sliced[-1] += array[index[0]:(index[1]+1)]
slicing(array, index[2:], stops, sliced)
sliced = [[]]
slicing(array, slice_, intervals, sliced)
sliced
# [[2, 3, 4, 5, 6, 7, 8, 9, 10], [12, 13, 14], [15, 16, 17]]
Data:
array = [7,8,2,3,4,10,5,6,7,10,8,9,10,4,5,12,13,14,1,2,15,16,17]
slice_ = [2, 4, 6, 8, 10, 12, 15, 17, 20, 22]
intervals = [12, 17, 22]
I have a list:
[55, 41, 45, 43, 60, 47, 33, 70, 42, 42, 44]
I would like to create a new list which ranks these items in the order they are:
Expected Output:
[7, ,2 ,9 ,10, 4, 11, 3, 6, 1, 5, 8]
Tried these 3 version of the func but its not working properly, not sure why?
def argsort(seq):
#return sorted(range(len(seq)), key = seq.__getitem__)
#return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]
return [x for x,y in sorted(enumerate(seq), key = lambda x: x[1])]
returns:
[6, 1, 8, 9, 3, 10, 2, 5, 0, 4, 7]
Let's come up with a more precise definition of what you are after:
Given a list L of numbers, create a list M that contains the valid indices of L, such that M[i] is the index at which the ith element of L occurs, when sorted. Present M as if the first element of L occurs at index 1.
Now, there are two ways of the valid indices of a list:
range(len(L)): gives a sequence of numbers 0... len(L)-1
enumerate(L): gives a sequence of tuples (0, L[0])... (len(L)-1, L[len(L)-1])
Since you want to operate under the assumption that list indices start at 1 (when in fact they start at 0 in python), we need to do a little off-setting
range(len(L)) becomes `range(1, len(L)+1)
enumerate(L) becomes enumerate(L, 1) (the optional argument tells enumerate to start numbering at 1)
Since we need the list items as well, let's use enumerate, rather than use range and do a lookup (I personally prefer this method, though both are valid)
So now, we can get a list of tuples, in which each tuple contains the index of an element in L and the corresponding element in L. We need to sort this by the elements themselves. This can be done with a call to sorted, with the optional key argument explaining that we should sort by the second element of the tuple (operator.itemgetter(1) says exactly this).
Once we have a sorted list of such tuples, all we need to do is extract the first element of each tuple (the index in L), we can use the list-comprehension [i[0] for i in mylist], or equivalently [operator.itemgetter(0)(t) for t in mylist]
Putting all these elements together, we get the following
In [138]: L = [55, 41, 45, 43, 60, 47, 33, 70, 42, 42, 44]
In [139]: [operator.itemgetter(0)(t) for t in sorted(enumerate(L,1), key=operator.itemgetter(1))]
Out[139]: [7, 2, 9, 10, 4, 11, 3, 6, 1, 5, 8]