We have the following numpy array:
b = np.array([[0.3, -0.2, 0.4, 0.5, -0.8, 1.0, 0.0, 0.0],
[0.6, 0.2, 0.7, 0.91, 0.67, 0.0, 1.0, 0.0],
[0.5, 0.1, 0.7, 0.0, 0.6, 0.0, 0.0, 1.0]])
We can see here that in the right side of this array (last 3 columns) we have a diagonal matrix. How can I get the column where 1 first occur in this diagonal matrix? i.e., column 5. I tried the following, which gives the correct answer:
first_occurence = np.argmax(b == 1, axis=1)[0]
But, if we have the following array, this does not work, giving me 0 as answer (which should be 6)
b = np.array([[0.3, -0.2, 0.4, 0.5, -0.8, 0.0, 0.0, 0.0],
[0.6, 0.2, 0.7, 0.91, 0.67, 0.0, 1.0, 0.0],
[0.5, 0.1, 0.7, 0.0, 0.6, 0.0, 0.0, 1.0]])
You can do this:
firsts = np.argmax(b == 1, axis=1)
first_occurence = min(firsts[firsts != 0])
The firsts[firsts != 0] argument to min() filters out rows for which b does not contain a 1, and min() then finds the column you're looking for.
UPDATE:
Assumptions, based on OP's clarifications:
the input contains a submatrix that is an identity matrix of order between 1 and b.shape[0] for input matrix b
the rightmost column of this identity matrix is to be found within the rightmost column of the input matrix
the top row of this identity matrix is between 0 and b.shape[0] - 1.
Here is a way to identify the column in the input matrix which contains the leftmost column in the embedded identity matrix:
def foo(b):
rows = b.shape[0]
left = b.shape[1] - rows
for tops in range(rows):
order = rows - tops
eye = np.eye(order)
for top in range(tops + 1):
if np.allclose(b[top:top + order, left:left + order], eye):
return left
left += 1
Test code:
b1 = np.array([
[0.3, -0.2, 0.4, 0.5, -0.8, 1.0, 0.0, 0.0],
[0.6, 0.2, 0.7, 0.91, 0.67, 0.0, 1.0, 0.0],
[0.5, 0.1, 0.7, 0.0, 0.6, 0.0, 0.0, 1.0]])
b2 = np.array([
[0.3, -0.2, 0.4, 0.5, -0.8, 0.0, 0.0, 0.0],
[0.6, 0.2, 0.7, 0.91, 0.67, 0.0, 1.0, 0.0],
[0.5, 0.1, 0.7, 0.0, 0.6, 0.0, 0.0, 1.0]])
b3 = np.array([
[0, -0.2, 0.4, 0.5, -0.8, 1.0, 0.0, 0.0],
[0.6, 1, 0.7, 0.91, 0.67, 0.0, 1.0, 0.0],
[0.5, 0.1, 0.7, 0.0, 0.6, 0.0, 0.0, 1.0]])
b4 = np.array([
[0.3, -0.2, 0.4, 0.5, -0.8, 0.0, 1.0, 0.0],
[0.6, 0.2, 0.7, 0.91, 0.67, 0.0, 0.0, 1.0],
[0.5, 0.1, 0.7, 0.0, 0.6, 0.0, 0.0, 1.0]])
print( foo(b1) )
print( foo(b2) )
print( foo(b3) )
print( foo(b4) )
Output:
5
6
5
6
Related
I am trying to multiply two lists with each other, take the sum of all elements and add the sum to the initial list.
I have two lists:
list_1 = [(1, 5, 6, 90), (9.3, 3.4, 9, 8), (8.4, 9, 9, 10)]
list_2 = [[0.0, 0.1, 0.2, 0.7], [0.0, 0.1, 0.3, 0.6], [0.0, 0.1, 0.6, 0.3]]
I want to multiply each element of list_1 with all entries of list_2
The result should look sth like this:
result = [[0, 0.5, 1.2, 63], [0, 0.5, 1.8, 45], [0, 0.5, 3.6, 27]]
afterward I would take the sum of the result and add the result to list_2
result_2 = [[0.0, 0.1, 0.2, 0.7, **64.7**], [0.0, 0.1, 0.3, 0.6, **47.3**], [0.0, 0.1, 0.6, 0.3, **31.1**]]
In a first step, I would like to store the final data in a list for each element of list_1
result_2_1= [[0.0, 0.1, 0.2, 0.7, **64.7**], [0.0, 0.1, 0.3, 0.6, **47.3**], [0.0, 0.1, 0.6, 0.3, **31.1**]]
result_2_2= same procedure but with List_1[1]
My current code works if list_1 has only one list (= list_1 = [(1, 5, 6, 90)]) but my attempts to loop through the list do not seem to work. I have used zip or loop through the entries but I always end up multiplying the lists... Here's my code that works so far.
list_1 = [(1, 5, 6, 90)]
list_2 = [[0.0, 0.1, 0.2, 0.7], [0.0, 0.1, 0.3, 0.6], [0.0, 0.1, 0.6, 0.3]]
n_list_1 = np.array(list_1)
n_list_2 = np.array(list_2)
m_result = n_list_1 * n_list_2
n_result = []
for i in range(0,len(m_result)):
n_result_1 = sum(m_result[i])
n_result.append(n_result_1)
list_2[i].append(list(n_result))
I hope you get what I am trying to do and have any suggestions on how to solve the problem.
import numpy as np
list_1 = [(1, 5, 6, 90)]
list_2 = [[0.0, 0.1, 0.2, 0.7], [0.0, 0.1, 0.3, 0.6], [0.0, 0.1, 0.6, 0.3]]
n_list_1 = np.array(list_1)
n_list_2 = np.array(list_2)
m_result = n_list_1 * n_list_2
n_result = []
for i in range(0,len(m_result)):
n_result_1 = sum(m_result[i])
n_result.append(n_result_1)
list_2[i].append(n_result[i])
print(list_2)
Just change list_2[i].append(list(n_result)) to list_2[i].append(n_result[i])
Note the sum of the second sublist should be 56.3
Output
[[0.0, 0.1, 0.2, 0.7, 64.69999999999999], [0.0, 0.1, 0.3, 0.6, 56.3], [0.0, 0.1, 0.6, 0.3, 31.1]]
If you want to use zip, you can try this code:
list_1 = [(1, 5, 6, 90), (9.3, 3.4, 9, 8), (8.4, 9, 9, 10)]
list_2 = [[0.0, 0.1, 0.2, 0.7], [0.0, 0.1, 0.3, 0.6], [0.0, 0.1, 0.6, 0.3]]
for inner_list1, inner_list2 in zip(list_1, list_2):
result = sum(a*b for a, b in zip(inner_list1, inner_list2))
inner_list2.append(result)
print(list_2)
Output:
[[0.0, 0.1, 0.2, 0.7, 64.69999999999999], [0.0, 0.1, 0.3, 0.6, 7.84], [0.0, 0.1, 0.6, 0.3, 9.3]]
Given lists are as follows:
mainList = [[0, 2, 1, 4, 3],
[0, 2, 1, 3, 4],
[1, 0, 2, 3, 4],
[2, 1, 0, 3, 4],
[1, 0, 2, 3, 4],
[0, 1, 2 ,3, 4],
[0, 2, 1, 3, 4]]
and list_indices = [0, 1, 2, 3, 4], list_value = [0.0, 0.2, 0.4, 0.4, 0.9].
The required list of lists is as follows:
mainList_mapped = [[0.0, 0.4, 0.2, 0.9, 0.4],
[0.0, 0.4, 0.2, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.4, 0.2, 0.0, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.0, 0.2, 0.4, 0.4, 0.9],
[0.0, 0.4, 0.2, 0.4, 0.9]]
Values of the mainList will be considered as indices and be replaced by the corresponding indices values in list_value. I tried but the code didn't work.
mainList_mapped = []
for ls in mainList:
for (i, j) in zip(ls, list_value):
ls[i] = j
mainList_mapped.append(ls)
A similar answer is here How to replace values at specific indexes of a python list? but I'm getting Error (TypeError: list indices must be integers or slices, not float) in getting my results. Any help will be appreciated.
You should be doing it like this:
mainList_mapped = []
for row in mainList:
row_mapped = []
for index in row:
row_mapped.append(list_value[index])
mainList_mapped.append(row_mapped)
You can create a function that rearranges a list based on given indices:
def rearrange(value, indices):
return [value[i] for i in indices]
Now apply this function to all the lists in the mainlist:
>>> result = [rearrange(list_value, indices) for indices in mainList]
>>> result
[[0.0, 0.4, 0.2, 0.9, 0.4],
[0.0, 0.4, 0.2, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.4, 0.2, 0.0, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.0, 0.2, 0.4, 0.4, 0.9],
[0.0, 0.4, 0.2, 0.4, 0.9]]
In this case it was easier because list_indices are sorted, but if it were shuffled, you could change the rearrange function like this:
mapping = dict(zip(list_indices, list_value))
def rearrange(mapping, indices):
return [mapping[i] for i in indices]
Try using a nested list comprehension:
print([[list_value[x] for x in i] for i in mainList])
Output:
[[0.0, 0.4, 0.2, 0.9, 0.4], [0.0, 0.4, 0.2, 0.4, 0.9], [0.2, 0.0, 0.4, 0.4, 0.9], [0.4, 0.2, 0.0, 0.4, 0.9], [0.2, 0.0, 0.4, 0.4, 0.9], [0.0, 0.2, 0.4, 0.4, 0.9], [0.0, 0.4, 0.2, 0.4, 0.9]]
I tried to compare drop height versus rebound height and have some data here:
drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
I want to select 5 random data points off of these variables, so I tried
smol_drop_heights = []
smol_rebound_heights = []
for each in range(0,5):
smol_drop_heights.append(drop_heights[randint(0, 9)])
smol_rebound_heights.append(rebound_heights[randint(0, 9)])
print(smol_drop_heights)
print(smol_rebound_heights)
When they print, they print different sets of data, and sometimes even repeat data, how do I fix this?
[0.8, 1.6, 0.6, 0.2, 0.12]
[1.02, 1.15, 0.88, 0.88, 0.6]
Here is a sample output, where you can see .88 is repeated.
A simple way to avoid repetitions and keep the data points paired and randomly sort the pairs:
from random import random
drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
pairs = list(sorted(zip(drop_heights, rebound_heights), key=lambda _: random()))[:5]
smol_drop_heights = [d for d, _ in pairs]
smol_rebound_heights = [r for _, r in pairs]
One way to do it would be:
drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
indices = [*range(len(drop_heights))]
from random import shuffle
shuffle(indices)
smol_drop_heights = []
smol_rebound_heights = []
for each in indices:
smol_drop_heights.append(drop_heights[each])
smol_rebound_heights.append(rebound_heights[each])
print(smol_drop_heights)
print(smol_rebound_heights)
Output:
[1.7, 0.8, 1.6, 1.2, 0.2, 0.4, 1.4, 2.0, 1.0, 0.6]
[1.34, 0.6, 1.15, 0.88, 0.16, 0.3, 1.02, 1.51, 0.74, 0.46]
Or, much shorter:
from random import sample
drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
paired = [*zip(drop_heights, rebound_heights)]
smol_drop_heights, smol_rebound_heights = zip(*sample(paired,5))
print(smol_drop_heights[:5])
print(smol_rebound_heights[:5])
Here"s what I would do.
import random
import numpy as np
k=5
drop_heights = np.array([0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0])
rebound_heights = np.array([0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51])
idx = random.sample(range(len(drop_heights )), k)
print(drop_heights[idx])
print(rebound_heights [idx])
You could try shuffling and then use the index of the original items like,
>>> drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
>>> rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
>>>
>>> import random
>>> d = drop_heights[:] # keep a copy to get index for making pairs later
>>> random.shuffle(drop_heights)
>>> # iterate through the new list and get the index of the item
>>> # from the original lists
>>> nd, nr = zip(*[(x,rebound_heights[d.index(x)]) for x in drop_heights])
>>> nd[:5]
(1.4, 0.6, 1.7, 0.2, 1.0)
>>> nr[:5]
(1.02, 0.46, 1.34, 0.16, 0.74)
or just use operator.itemgetter and random.sample like,
>>> drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
>>> rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
>>>
>>> import random, operator
>>> indexes = random.sample(range(len(drop_heights)), 5)
>>> indexes
[5, 0, 4, 7, 3]
>>> f = operator.itemgetter(*indexes)
>>> f(drop_heights)
(1.2, 0.2, 1.0, 1.6, 0.8)
>>> f(rebound_heights)
(0.88, 0.16, 0.74, 1.15, 0.6)
Your problem is that when you call randint, it gives a different random number each time. To solve this you would need to save an index variable, to a random number, each time the code loops, so that you add the same random variable each time.
for each in range(0, 4):
index = randint(0, 9)
smol_drop_heights.append(drop_heights[index])
smol_rebound_heights.append(rebound_heights[index])
print(smol_drop_heights)
print(smol_rebound_heights)
To solve the problem about repeats, just check if the lists already have the variable you want to add, you could do it with either variable, as neither of them have repeats in them, and since there may be repeats, a for loop will not be sufficient, so you will have to repeat until the lists are full.
So my final solution is:
while True:
index = randint(0, 9)
if drop_heights[index] not in smol_drop_heights:
smol_drop_heights.append(drop_heights[index])
smol_rebound_heights.append(rebound_heights[index])
if len(smol_drop_heights) == 4:
break
print(smol_drop_heights)
print(smol_rebound_heights)
And since you may want to arrange those value in order, you may do this:
smol_drop_heights = []
smol_rebound_heights = []
while True:
index = randint(0, 9)
if drop_heights[index] not in smol_drop_heights:
smol_drop_heights.append(drop_heights[index])
smol_rebound_heights.append(rebound_heights[index])
if len(smol_drop_heights) == 4:
smol_drop_heights.sort()
smol_rebound_heights.sort()
break
print(smol_drop_heights)
print(smol_rebound_heights)
Ok, you want to do two things, pair your lists. The idiomatic way to do this is to use zip:
drop_heights = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.7, 2.0]
rebound_heights = [0.16, 0.30, 0.46, 0.6, 0.74, 0.88, 1.02, 1.15, 1.34, 1.51]
paired = list(zip(drop_heights, rebound_heights))
Then, you want to sample five pairs from this. So use random.sample:
sampled = random.sample(paired, 5)
Finally, if you need them to be in seperate lists (you probably don't, but if you must), you can unpack it like this:
smol_drop_heights, smol_rebound_heights = zip(*sampled)
You can actually just do this in all at once, although it might become a bit unreadable:
smol_drop_heights, smol_rebound_heights = zip(*random.sample(list(zip(drop_heights, rebound_heights)), 5))
I have a numpy array like this:
a = [[0.04393, 0.0, 0.0], [0.04393, 0.005, 0.0], [0.04393, 0.01, 0.0],[0.04393, 0.015, 0.0]]
And i want to format it in this:
b = [((0.04393, 0.0, 0.0), ), ((0.04393, 0.005, 0.0), ), ((0.04393,
0.01, 0.0), ), ((0.04393, 0.015, 0.0), )]
How can i do it?
This will do:
a = [[0.04393, 0.0, 0.0], [0.04393, 0.005, 0.0], [0.04393, 0.01, 0.0],[0.04393, 0.015, 0.0]]
b = [ (tuple(a1),) for a1 in a]
I'm having trouble with an algorithm in python.
I have an array of 4 values [a,b,c,d] those are percentages so at any given time a+b+c+d=1. I need a loop that goes through all possible combinations of these numbers with a stepsize of 0.1. Example:
[0,0,0,1]
[0,0,0.1,0.9]
[0,0.1,0.1,0.8]
[0.1,0.1,0.1,0.7]
.....
[0.1,0.1,0.2,0.6]
[0.1,0.1,0.3,0.5]
....
[1,0,0,0]
I created a code that seems to overflow... any help? ty I Know its a noob question...
def frange(start, stop, step):
while start <= stop:
yield start
start += step
def distribuir(p,array):
if len(array) == 3:
array.append(p)
print(Array)
return
for i in frange(0,1,0.1):
temp = []
temp.append(array)
temp.append(i)
distribuir(p-i,temp)
A naive recursive solution with a lot of room for optimization:
import itertools
def possibilities(prefix, size, values, total):
if size == 0:
return [prefix] if sum(prefix) == total else []
return itertools.chain(*map(
lambda v: possibilities(prefix+[v], size-1, values, total),
values
))
Example:
list(
map(
lambda t: map(float, t),
possibilities(
prefix=[],
size=3,
values=map(Decimal, ['0', '0.1', '0.2', '0.3']),
total=Decimal('0.4')
)
)
)
Output:
[[0.0, 0.1, 0.3],
[0.0, 0.2, 0.2],
[0.0, 0.3, 0.1],
[0.1, 0.0, 0.3],
[0.1, 0.1, 0.2],
[0.1, 0.2, 0.1],
[0.1, 0.3, 0.0],
[0.2, 0.0, 0.2],
[0.2, 0.1, 0.1],
[0.2, 0.2, 0.0],
[0.3, 0.0, 0.1],
[0.3, 0.1, 0.0]]