How to extract elements in an array with regard to an index? - python-3.x

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]]

Related

Remove columns that contain only zeros in a matrix on Python

I am building a matrix on python and once it's built, I would like to remove all the columns that contains only zeros. (Some columns contain zeros but not only so i want to keep them.
def remove_column_with_all_zeros(matrix):
zero_columns = []
for i in range(len(matrix[0])):
column = [row[i] for row in matrix]
if all(val == 0 for val in column):
zero_columns.append(i)
for i in sorted(zero_columns, reverse=True):
for row in matrix:
del row[i]
return matrix
I tried this function but it doesn't work.
Thank you
So convert your matrix into np array if it is not:
So this is an example:
Here you would like to remove first column I guess
array([[0, 0, 1],
[0, 2, 3],
[0, 1, 4]])
So if you have your matrix as the above example you may then do:
matrixT = matrix.T
# This will return a boolean that will have True value where all the elements of a column are 0
all_zeros = (matrixT==0).all(1)
updated_matrix = np.delete(matrix, all_zeros, axis =1)
Output for my example :
array([[0, 1],
[2, 3],
[1, 4]])
Let me know if it works for you!!

matrix addition giving wrong answer

I am from java background, I am learning python matrix operation. I have an assignment question to add two matrices manually I can't figure out the error in my logic. need help thank you
x = [[12,7,3],[4 ,5,6],[7 ,8,9]]
y = [[5,8,1],[6,7,3],[4,5,9]]
row = len(x)
col = len(x[0])
ans = [[0] * col] * row
for i in range(len(x)):
for j in range(len(x[i])):
ans[i][j] = x[i][j] + y[i][j]
print()
print(ans)
output :
[[11, 13, 18], [11, 13, 18], [11, 13, 18]]
The problem is here:
ans = [[0]*col]*row
This statement creates row number of objects, where each object is [[0]*col]. What this means is that, each "sub-list" in the list is pointing to the same list.
(More information about this behaviour here: List of lists changes reflected across sublists unexpectedly)
You can verify that by checking the id values of ans[0],ans[1] and so on:
>>> a = [[0]*col]*row
>>>
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> id(a[0])
140336190913992
>>> id(a[1])
140336190913992
>>> id(a[2])
140336190913992
This means, if we set a[0][1] = 10 (say), then EACH sub-list will have the the value 10 set. This is because all the lists point to the same list.
i.e.
>>> a[0][1] = 10
>>> a
[[0, 10, 0], [0, 10, 0], [0, 10, 0]]
Now, how do we avoid this?
You can do so by initiliasing the ans list in a different way, as in:
b = [[0 for x in range(col)] for y in range(row)]
You can verify that all the sub-lists point to different addresses by using id again:
>>> id(b[0])
140336190512520
>>> id(b[1])
140336190765000
>>> id(b[2])
140336197031816
So now if you run your original program, you will get desired results.
TLDR; your modified program looks like this:
x = [[12,7,3],[4 ,5,6],[7 ,8,9]]
y = [[5,8,1],[6,7,3],[4,5,9]]
row = len(x)
col = len(x[0])
ans = [[0 for x in range(col)] for y in range(row)]
for i in range(len(x)):
for j in range(len(x[i])):
ans[i][j] = x[i][j] + y[i][j]
print(ans)

Shortcut for all the possible permutation of a set of numbers for m digits

I have been working on finite field. Suppose I have a prime number p=7. So I get a list q=[0,1,2,3,4,5,6]. Now I want all the possible permutation of the elements of set q for 7 places. For example [1,1,1,4,6,3,1] is one of the possible permutation. Is there any inbuilt command in python for doing that? Actually I am working with bigger field where P is 127 (p=127).
Those aren't permutations because elements are repeated, this looks more like a product.
you can use itertools.product on repeated q lists (here for 3 elements):
import itertools
q=[0,1,2] # or q = list(range(3))
for z in itertools.product(*(q,)*len(q)): # using arg unpacking like if it was (q,q,q)
z = list(z) # to convert as list
print(z)
prints:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 0]
[0, 1, 1]
[0, 1, 2]
...snip...
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]
for p=3 it prints 3**3 = 27 values. If p=127 well... sounds not reasonable.

Returning the N largest values' indices in a multidimensional array (can find solutions for one dimension but not multi-dimension)

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]

Make specific elements of numpy matrix as 0

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

Resources