I have got index of 0 elements of Numpy Matrix (M) using:
index_array = numpy.argwhere(M == 0)
Now, I want to make these index elements (index present in index_array) as 0 in other matrix B. Is there any numpy way to do this?
For eg : index_array contains
[[2 1]
[4 4]]
, so make element present at (2,1) and (4,4) in Matrix B as 0.
You should have used np.where which returns a tuple of row and col index and thus can be used as indexing directly, instead of argwhere, so long as the index is not out of bound for B, you can do:
B[np.where(M == 0)] = 0
Example:
M = np.array([[1,2],[3,0],[0,1]])
M
#array([[1, 2],
# [3, 0],
# [0, 1]])
B = np.array([[1,2,3],[4,5,6],[7,8,9]])
B
#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
B[np.where(M == 0)] = 0
B
#array([[1, 2, 3],
# [4, 0, 6],
# [0, 8, 9]])
If you want to stick to np.argwhere, you can get the row index and col index respectively and then do the assignment:
index_array = np.argwhere(M == 0)
B[index_array[:,0], index_array[:,1]] = 0
Related
I have a row A = [0 1 2 3 4] and an index I = [0 0 1 0 1]. I would like to extract the elements in A indexed by I, i.e. [2, 4].
My attempt:
import numpy as np
A = np.array([0, 1, 2, 3, 4])
index = np.array([0, 0, 1, 0, 1])
print(A[index])
The result is not as I expected:
[0 0 1 0 1]
Could you please elaborate on how to achieve my goal?
I think you want boolean indexing:
A[index.astype(bool)]
# array([2, 4])
A non-numpy way to achieve this, in case its useful - it uses zip to combine each pair of elements, and returns the first if the second is true:
[x[0] for x in zip(a, i) if x[1]]
So say I have a list sequences such as this.
I want to remove all sequences where its total sum = N and/or it has a contiguous subarray with sum = N.
For example, if N = 4, then (1,1,2) is not valid since its total is 4. (1,1,3) is also not valid since the (1,3) is also 4. (1,3,1) is also not valid for the same reason.
lst = [
(1,1,1), (1,1,2), (1,1,3),
(1,2,1), (1,2,2), (1,2,3),
(1,3,1), (1,3,2), (1,3,3),
(2,1,1), (2,1,2), (2,1,3),
(2,2,1), (2,2,2), (2,2,3),
(2,3,1), (2,3,2), (2,3,3),
(3,1,1), (3,1,2), (3,1,3),
(3,2,1), (3,2,2), (3,2,3),
(3,3,1), (3,3,2), (3,3,3)
]
E.g.
Input: 4 3
Output: 2 1 2
So what I have right now is
lst = [t for t in list(product(range(1,n),repeat=n-1)) if not any((sum(t[l:h+1]) % n == 0) for l, h in combinations(range(len(t)), 2))]
Currently it is in O(n2) if I'm not mistaken. What would be a better way to do this?
If you can use numpy, you can concatenate the total sum of each tuple with the contiguous value sums, then check if any of your resultign elements are equal to 4:
arr = np.array(lst)
arr[~(np.concatenate((np.sum(arr,axis=1).reshape(-1,1),
(arr[:,:-1]+ arr[:,1:])),axis=1) == 4).any(1)]
# or:
arr[(np.concatenate((np.sum(arr,axis=1).reshape(-1,1),
(arr[:,:-1]+ arr[:,1:])),axis=1) != 4).all(1)]
Returning:
array([[1, 1, 1],
[1, 2, 3],
[2, 1, 2],
[2, 3, 2],
[2, 3, 3],
[3, 2, 1],
[3, 2, 3],
[3, 3, 2],
[3, 3, 3]])
I have two lists.
a_num = [1, 3, 2, 4]
b_num = [1, 2, 3, 4]
I want to find a permutation matrix to convert a to b. Mathematically, a permutation matrix is a square matrix, whose elements are either 1 or 0. It can change the sequence of elements in a vector, by multiplying it.
In this particular example, the permutation matrix is:
p = [[1,0,0,0],
[0,0,1,0],
[0,1,0,0],
[0,0,0,1]]
# check whether p is correct.
b_num == np.dot(np.array(p), np.array(a_num).reshape(4,1))
Could you please show me how to make that matrix p? In my real application, there can be tens of elements in the lists with arbitrary sequence. And the two lists always contain str instead of int.
And how to make p when the a and b are lists of str?
a_str = ['c1', 'c2', 's1', 's2']
b_str = ['c1', 's1', 'c2', 's2']
In pure Python you can do:
a_str = ['c1', 'c2', 's1', 's2']
b_str = ['c1', 's1', 'c2', 's2']
from collections import defaultdict
dd = defaultdict(lambda: [0, []])
for i, x in enumerate(b_str): # collect indexes of target chars
dd[x][1].append(i)
matrix = [[0]*len(a_str) for x in b_str]
for i, a in enumerate(a_str):
# set cell at row (src index) and col (next tgt index) to 1
matrix[i][dd[a][1][dd[a][0]]] = 1
# increment index for looking up next tgt index
dd[a][0] += 1
matrix
# [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]
This assumes that a_str and b_str are in fact respective permutations.
Edit: works only with numbers.
For arrays with the same length using NumPy:
import numpy as np
a_num = [1, 3, 2, 4]
b_num = [4, 2, 3, 1]
a = np.array(a_num)
b = np.array(b_num)
len_v = len(a) # = len(b)
A = np.zeros((len_v, len_v))
A[np.argsort(a), np.arange(len_v)] = 1
B = np.zeros((len_v, len_v))
B[np.argsort(b), np.arange(len_v)] = 1
np.dot(np.linalg.inv(B), np.dot(A, a)) # array([4., 2., 3., 1.])
I have a numpy array X, and I'd like to return another array Y whose entries are the indices of the n largest values of X i.e. suppose I have:
a =np.array[[1, 3, 5], [4, 5 ,6], [9, 1, 7]]
then say, if I want the first 5 "maxs"'s indices-here 9, 7 , 6 , 5, 5 are the maxs, and their indices are:
b=np.array[[2, 0], [2 2], [ 2 1], [1 1], [0 , 2])
I've been able to find some solutions and make this work for a one dimensional array like
c=np.array[1, 2, 3, 4, 5, 6]:
def f(a,N):
return np.argsort(a)[::-1][:N]
But have not been able to generate something that works in more than one dimension. Thanks!
Approach #1
Get the argsort indices on its flattened version and select the last N indices. Then, get the corresponding row and column indices -
N = 5
idx = np.argsort(a.ravel())[-N:][::-1] #single slicing: `[:N-2:-1]`
topN_val = a.ravel()[idx]
row_col = np.c_[np.unravel_index(idx, a.shape)]
Sample run -
# Input array
In [39]: a = np.array([[1,3,5],[4,5,6],[9,1,7]])
In [40]: N = 5
...: idx = np.argsort(a.ravel())[-N:][::-1]
...: topN_val = a.ravel()[idx]
...: row_col = np.c_[np.unravel_index(idx, a.shape)]
...:
In [41]: topN_val
Out[41]: array([9, 7, 6, 5, 5])
In [42]: row_col
Out[42]:
array([[2, 0],
[2, 2],
[1, 2],
[1, 1],
[0, 2]])
Approach #2
For performance, we can use np.argpartition to get top N indices without keeping sorted order, like so -
idx0 = np.argpartition(a.ravel(), -N)[-N:]
To get the sorted order, we need one more round of argsort -
idx = idx0[a.ravel()[idx0].argsort()][::-1]
For a given array v=[1,2,3] I am trying to print the sum of the product of each element with s for a range of s
import numpy as np
v=[1,2,3]
for s in range(0,5):
for i in range (0,3):
tot= np.multiply(v[i],s)
b.append(tot)
print (b)
my output is
[0, 0, 0, 1, 2, 3, 2, 4, 6, 3, 6, 9, 4, 8, 12]
I am trying to get the out put as
[[0, 0, 0], [1, 2, 3], [2, 4, 6], [3, 6, 9], [4, 8, 12]]
I am not quite sure how the second for loop is working inside the first for loop. If someone can explain that, it would be wonderful.
You'd create a new list for each iteration of the outer for loop:
v=[1,2,3]
b = []
for s in range(0,5):
result = []
for i in range (0,3):
tot= np.multiply(v[i],s)
result.append(tot)
b.append(result)
print (b)
You could just use * to multiply values, and you can iterate directly over v (no need to use a range)`:
v = [1, 2, 3]
b = []
for s in range(5):
result = []
for i in v:
result.append(i * s)
b.append(result)
You can replace both loops with list comprehensions:
b = [[i * s for i in v] for s in range(5)]
import numpy as np
v=np.array([1,2,3])
b=[]
for s in range(0,5):
b.append(list(v*s))
print (b)
Should do what you want. Don't forget numpy's extremely powerful broadcasting capability.
v=[1,2,3]
b=[]
for s in range(0,5):
b.append([])
for i in range (0,3):
tot= np.multiply(v[i],s)
b[s].append(tot)
print(b)