how to replace an array containing indices with values from another array? - python

I have an array b containing indices of an array a. I want to insert values of another array c in the array b with same indices.
import numpy as np
a1=np.array([[1, 3, 5, 2, 3],[7, 6, 5, 2, 4],[2, 0, 5, 6, 4]])
a=a1.argsort()[:,:2]
## this will create an array with indices of 2 smallest values of a1
a
[[0 3]
[3 4]
[1 0]]
b=np.array([[1],[2],[3],[4],[5],[6]])
now I want to replace value 0 in a with 1 in b ; 3 with 4 and so on
i tried using:
[a[index]]=b[index]
but its obviously not the right way as array a handles these indices as values
please help

If I understood you correctly, you can just use the flattened version of a to index into b:
result = b.ravel()[a.ravel()]
[1, 4, 4, 5, 2, 1]
If you need it in the same dimensions as a you can reshape it:
result = result.reshape(a.shape)
[[1, 4]
[4, 5]
[2, 1]]

Related

Find the row index number of an array in a 2D numpy array

If I have a 2D numpy array A:
[[6 9 6]
[1 1 2]
[8 7 3]]
And I have access to array [1 1 2]. Clearly, [1 1 2] belongs to index 1 of array A. But how do I do this?
Access the second row using the following operator:
import numpy as np
a = np.array([[6, 9, 6],
[1, 1, 2],
[8, 7, 3]])
row = [1, 1, 2]
i = np.where(np.all(a==row, axis=1))
print(i[0][0])
np.where will return a tuple of indices (lists), which is why you need to use the operators [0][0] consecutively in order to obtain an int.
One option:
a = np.array([[6, 9, 6],
[1, 1, 2],
[8, 7, 3]])
b = np.array([1, 1, 2])
np.nonzero((a == b).all(1))[0]
output: [1]
arr1 = [[6,9,6],[1,1,2],[8,7,3]]
ind = arr1.index([1,1,2])
Output:
ind = 1
EDIT for 2D np.array:
arr1 = np.array([[6,9,6],[1,1,2],[8,7,3]])
ind = [l for l in range(len(arr1)) if (arr1[l,:] == np.array([1,1,2])).all()]
import numpy as np
a = np.array([[6, 9, 6],
[1, 1, 2],
[8, 7, 3]])
b = np.array([1, 1, 2])
[x for x,y in enumerate(a) if (y==b).all()] # here enumerate will keep the track of index
#output
[1]

In a specific row of a numpy array, how to find column indexes of the top 3 largest values

I have an array X:
X = np.array([[4, 3, 5, 2],
[9, 6, 7, 3],
[8, 6, 7, 5],
[3, 4, 5, 3],
[5, 3, 2, 6]])
I want the indices of the top 3 greatest values in a row with index 1. The result of that would be :
[0,2,1]
I am relatively new to Python. I tried doing it with argsort, but am not able to do it for one specific row.
You can use argsort on axis=1 (by row) and then extract the last 3 indices for each row:
X.argsort(axis=1)[:,:-4:-1]
#[[2 0 1]
# [0 2 1]
# [0 2 1]
# [2 1 3]
# [3 0 1]]
X = np.array([[4, 3, 5, 2],
[9, 6, 7, 3],
[8, 6, 7, 5],
[3, 4, 5, 3],
[5, 3, 2, 6]])
# get top 3 values in the row with index 1
row_sorted = sorted(X[1], reverse=True)[0:3]
# Find the corresponding index of theses top 3 values
indexes = [list(X[1]).index(i) for i in row_sorted]
output:
[0, 2, 1]
For sufficiently large arrays, np.argpartition will be the most efficient solution. It will place the last three elements of the sort indices in the right positions:
i = np.argpartition(x[1], [-3, -2, -1])[:-4:-1]
This behaves similarly to np.argsort except that only the selected indices are in the right place. All the other elements are only guaranteed to be in the correct side relative to each partition point, but not the exact position.

Summing columns of a 2D tensor according to multiple sets of indices

In tensorflow, I would like to sum columns of a 2D tensor according to multiple sets of indices.
For example:
Summing the columns of the following tensor
[[1 2 3 4 5]
[5 4 3 2 1]]
according to the 2 sets of indices (first set to sum columns 0 1 2 and second set to sum columns 3 4)
[[0,1,2],[3,4]]
should give 2 columns
[[6 9]
[12 3]]
Remarks:
All columns' indices will appear in one and only one set of indices.
This has to be done in Tensorflow, so that gradient can flow through this operation.
Do you have any idea how to perform that operation? I suspect I need to use tf.slice and probably tf.while_loop.
You can do that with tf.segment_sum:
import tensorflow as tf
nums = [[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1]]
column_idx = [[0, 1, 2], [3, 4]]
with tf.Session() as sess:
# Data as TF tensor
data = tf.constant(nums)
# Make segment ids
segments = tf.concat([tf.tile([i], [len(lst)]) for i, lst in enumerate(column_idx)], axis=0)
# Select columns
data_cols = tf.gather(tf.transpose(data), tf.concat(column_idx, axis=0))
col_sum = tf.transpose(tf.segment_sum(data_cols, segments))
print(sess.run(col_sum))
Output:
[[ 6 9]
[12 3]]
I know of a crude way of solving this in NumPy if you don't mind solving this problem with NumPy.
import numpy as np
mat = np.array([[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]])
grid1 = np.ix_([0], [0, 1, 2])
item1 = np.sum(mat[grid1])
grid2 = np.ix_([1], [0, 1, 2])
item2 = np.sum(mat[grid2])
grid3 = np.ix_([0], [3, 4])
item3 = np.sum(mat[grid3])
grid4 = np.ix_([1], [3, 4])
item4 = np.sum(mat[grid4])
result = np.array([[item1, item3], [item2, item4]])

concatinate numpy matrices to get an array with dimension 3

I want to concatenate numpy matrices that have different shapes in order to get an array with dimension=3.
example :
A= [[2 1 3 4]
[2 4 0 6]
[9 5 7 4]]
B= [[7 2 8 4]
[8 6 8 6]]
and result what I need should be like that:
C=[[[2 1 3 4]
[2 4 0 6]
[9 5 7 4]]
[[7 2 8 4]
[8 6 8 6]]]
Thanks for help
If I understand your question correctly, a 3dim numpy array is probably not the way to represent your data, because there's no definitive shape.
A 3dim numpy array should have a shape of the form N1 x N2 x N3, whereas in your case each "2dim row" has a different shape.
Alternatives would be to keep your data in lists (or a list of arrays), or to use masked arrays, if that happens to be reasonable in you case.
You can only convert to a 3D np.ndarray in a useful manner if A.shape == B.shape. In that case all you need to do is e.g. C = np.array([A, B]).
import numpy as np
A = np.array([[2, 1, 3, 4],
[9, 5, 7, 4]])
B = np.array([[7, 2, 8, 4],
[8, 6, 8, 6]])
C = np.array([A, B])
print C
Because A and B have different sizes (# of rows), the best you can do make an array of shape (2,) and dtype object. Or at least that's what a simple construction gives you:
In [9]: np.array([A,B])
Out[9]:
array([array([[2, 1, 3, 4],
[2, 4, 0, 6],
[9, 5, 7, 4]]),
array([[7, 2, 8, 4],
[8, 6, 8, 6]])], dtype=object)
But constructing an array like this doesn't help much. Just use the list [A,B].
np.vstack([A,B]) produces a (5,4) array.
np.array([A[:2,:],B]) gives a (2,2,4) array. Or you could pad B so they are both (3,4).
So one way or other you need to redefine your problem.

How to use numpy's hstack?

I have one large numpy.ndarray array that I want to extract the 4th and 5th columns out of and put those columns into a 2D array. The [i,0] element should be the value on the 4th column and [i,1] should be the element from the 5th column.
I trying to use the numpy.hstack function to do this.
a = numpy.asarray([1, 2, 3, 4, 5])
for i in range(5):
a = numpy.vstack([a, numpy.asarray([1, 2, 3, 4, 5])])
combined = np.hstack([a[:,3], a[:,4]])
However, this simply gives me an nx1 array. I have tried multiple approaches using concatenate that look like these examples:
combined = np.concatenate([a[:,3], a[:,4]])
combined = np.concatenate([a[:,3], a[:,4]], axis=1)
combined = np.concatenate([a[:,3].T, a[:,4].T])
I feel like hstack is the function I want, but I can't seem to figure out how to make it give me an nx2 array. Can anyone point me in the right direction? Any help is appreciated.
Just slice out your data as follows:
X = [[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]]
slicedX = X[:,3:5]
results in:
[[3 4]
[3 4]
[3 4]
[3 4]]
I think this will do what you want:
a[:,[3,4]]
You can also use zip:
>>> c = numpy.array( zip( a[:, 3], a[:, 4]) )
>>> c
array([[4, 5],
[4, 5],
[4, 5],
[4, 5],
[4, 5],
[4, 5]])

Categories