Selecting 3 random elements from an array in python - python

I am trying to select three random elements from within a array.
I currently have implemented:
result= np.random.uniform(np.min(dataset[:,1]), np.max(dataset[:,1]), size=3
Which returns three random floats between the min and max range. I am struggling finding a way to select random elements within an array, instead of a random float which may not exist as an element inside the array.
I have also tried:
result = random.choice(dataset[:,0])
Which only returns a single element, is it possible to return 3 with this function

You can use random.sample(), if you want to sample without replacement, ie. the same element can't be picked twice.
>>> import random
>>> l = [0.3, 0.2, 0.1, 0.4, 0.5, 0.6]
>>> random.sample(l, 3)
[0.3, 0.5, 0.1]
If you want to sample with replacement, you can random.choices()
>>> import random
>>> l = [0.3, 0.2, 0.1, 0.4, 0.5, 0.6]
>>> random.choices(l, k=3)
[0.3, 0.5, 0.3]

You can use random.choices instead:
result = random.choices(dataset[:,0], k=3)

Related

Change one weight in a list and adjust all other weights accordingly so that the sum of the list is 1.0 again

I have a list of weights which all have a value range between 0.0 and 1.0. The sum of the values in list should be always 1.0.
Now I would like to write a function in which I can change one weight from the list by a certain value (positive or negative). The remaining weights of the lst should be adjusted evenly, so that the sum of the list result in 1.0 again at the end.
Example:
weights = [0.5, 0.2, 0.2, 0.1]
If I increase the second entry of the list by 0.3, the resulting list should look like this:
weights = [0.4, 0.5, 0.1, 0.0]
I've tried with the following function:
def change_weight(weights, index, value):
result = []
weight_to_change = weights[index] + value
weights.pop(index)
for i, weight in enumerate(weights):
if i == index:
result.append(weight_to_change)
result.append(weight - value/len(weights))
return result
This works perfectly for the example above:
weights = [0.5, 0.2, 0.2, 0.1]
print(change_weight(weights, 1, 0.3))
# like expected: [0.4, 0.5, 0.1, 0.0]
However, if I want to change the second weight about 0.5. The the last element of the list will get a negative value:
weights = [0.5, 0.2, 0.2, 0.1]
print(change_weight(weights, 1, 0.5))
results in [0.33, 0.7, 0.03, -0.07]
However, I do not want any negative values in the list. Such values should instead be set to 0.0 and the remainder added or subtracted evenly to the other values.
Does anyone have an idea how I can implement this?
Here is a implementation of the idea of #RemiCuingnet :
def change_weight(weights, index, value):
new_weight = weights[index] + value
old_sum = sum(w for i,w in enumerate(weights) if i != index)
new_weights = []
for i,w in enumerate(weights):
if i == index:
new_weights.append(new_weight)
else:
new_weights.append(w*(1-new_weight)/old_sum)
return new_weights
For example
print(change_weight([0.5, 0.2, 0.2, 0.1],1,.3))
print(change_weight([0.5, 0.2, 0.2, 0.1],1,.5))
Output:
[0.3125, 0.5, 0.12500000000000003, 0.06250000000000001]
[0.18750000000000006, 0.7, 0.07500000000000002, 0.03750000000000001]

How to get elements from a specific range out of a list?

Does anybody have an idea how to get the elements in a list whose values fall within a specific (from - to) range?
I need a loop to check if a list contains elements in a specific range, and if there are any, I need the biggest one to be saved in a variable..
Example:
list = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
# range (0.5 - 0.58)
# biggest = 0.56
You could use a filtered comprehension to get only those elements in the range you want, then find the biggest of them using the built-in max():
lst = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
biggest = max([e for e in lst if 0.5 < e < 0.58])
# biggest = 0.56
As an alternative to other answers, you can also use filter and lambda:
lst = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
biggest = max([i for i in filter(lambda x: 0.5 < x < 0.58, lst)])
I suppose a normal if check would be faster, but I'll give this just for completeness.
Also, you should not use list = ... as list is a built-in in python.
You could also go about it a step at a time, as the approach may aid in debugging.
I used numpy in this case, which is also a helpful tool to put in your tool belt.
This should run as is:
import numpy as np
l = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
a = np.array(l)
low = 0.5
high = 0.58
index_low = (a < high)
print(index_low)
a_low = a[index_low]
print(a_low)
index_in_range = (a_low >= low)
print(index_in_range)
a_in_range = a_low[index_in_range]
print(a_in_range)
a_max = a_in_range.max()
print(a_max)

Is there any way to insert values in a specific list dynamically? [duplicate]

This question already has answers here:
How can I select a variable by (string) name?
(5 answers)
Closed 8 months ago.
I'm trying to insert values in a list using the name of a variable dynamically but I am not being able to do it.
lst_prio = [90, 100]
p_90 = [0.11, 0.2, 0.15, 0.6, 0.9]
p_100 = [0.1, 0.3, 0.5, 0.7, 0.8]
lst_crv = [4,3,2,5,6]
crv = [1,2,3,4,5]
lst_percs = []
for x in range(len(lst_prio)):
lst_percs.append("lst_p_"+str(lst_prio[x]))
dic =dict(zip(lst_prio,lst_percs))
for w in range(len(lst_prio)):
dic[lst_prio[w]] =[]
for i in range(len(crv)):
for j in range(len(lst_crv)):
if crv[i] == lst_crv[j]:
#Below I would like to insert the list as the append value (p_90 to p_100) dynamically based on the dictionary I've created
dic[lst_prio[w]].append(p_90[i])
The result I am getting (because I am not being able to iterate):
lst_p_90 = [0.2, 0.15, 0.6, 0.9]
lst_p_90 = [0.2, 0.15, 0.6, 0.9]
The result I would like:
lst_p_90 = [0.2, 0.15, 0.6, 0.9]
lst_p_100 = [0.3, 0.5, 0.7, 0.8]
I think I get what you meant. You want to dynamically evaluate the variable based on the name. Try this for the last lines.
if crv[i] == lst_crv[j]:
number = lst_prio[w]
p_n = locals()['p_' + str(number)]
dic[number].append(p_n[i])
Related: How to get the value of a variable given its name in a string?

Sample from a 2d probability numpy array?

Say that I have an 2d array ar like this:
0.9, 0.1, 0.3
0.4, 0.5, 0.1
0.5, 0.8, 0.5
And I want to sample from [1, 0] according to this probability array.
rdchoice = lambda x: numpy.random.choice([1, 0], p=[x, 1-x])
I have tried two methods:
1) reshape it into a 1d array first and use numpy.random.choice and then reshape it back to 2d:
np.array(list(map(rdchoice, ar.reshape((-1,))))).reshape(ar.shape)
2) use the vectorize function.
func = numpy.vectorize(rdchoice)
func(ar)
But these two ways are all too slow, and I learned that the nature of the vectorize is a for-loop and in my experiments, I found that map is no faster than vectorize.
I thought this can be done faster. If the 2d array is large it would be unbearably slow.
You should be able to do this like so:
>>> p = np.array([[0.9, 0.1, 0.3], [0.4, 0.5, 0.1], [0.5, 0.8, 0.5]])
>>> (np.random.rand(*p.shape) < p).astype(int)
Actually I can use the np.random.binomial:
import numpy as np
p = [[0.9, 0.1, 0.3],
[0.4, 0.5, 0.1],
[0.5, 0.8, 0.5]]
np.random.binomial(1, p)

Find index of the first value that is below/above a threshold

I have a list with a series of random floats that go from negative to positive, like:
values = [0.001, 0.05, 0.09, 0.1, 0.4, 0.8, 0.9, 0.95, 0.99]
I wish to filter out the indices that first meet the greater than/less than values that I wish. For example, if I want the first closest value less than 0.1 I would get an index of 2 and if I want the first highest value greater than 0.9 I'd get 7.
I have a find_nearest method that I am using but since this dataset is randomized, this is not ideal.
EDIT: Figured out a solution.
low = next(x[0] for x in enumerate(list(reversed(values))) if x[1] < 0.1)
high = next(x[0] for x in enumerate(values) if x[1] > 0.9)
if the values list gets long you may want the bisect module from the standard lib
bisect_left, bisect_right may serve as the >, < tests
import bisect
values = [0.001, 0.05, 0.09, 0.1, 0.4, 0.8, 0.9, 0.95, 0.99]
bisect.bisect_left(values, .1)
Out[226]: 3
bisect.bisect_right(values, .1)
Out[227]: 4

Categories