Numpy indexing with list of lists [duplicate] - python

This question already has answers here:
Indexing one array by another in numpy
(4 answers)
Closed 3 years ago.
I have a list of lists of indices for an numpy array, but do not quite come to the wanted result when using them.
n = 3
a = np.array([[8, 1, 6],
[3, 5, 7],
[4, 9, 2]])
np.random.seed(7)
idx = np.random.choice(np.arange(n), size=(n, n-1))
# array([[0, 1],
# [2, 0],
# [1, 2]])
In this case I want:
element 0 and 1 of row 0
element 2 and 0 of row 1
element 1 and 2 of row 2
My list has n sublists and all of those lists have the same length.
I want that each sublist is only used once and not for all axis.
# Wanted result
# b = array[[8, 1],
# [7, 3],
# [9, 2]])
I can achieve this but it seems rather cumbersome with a lot of repeating and reshaping.
# Possibility 1
b = a[:, idx]
# array([[[8, 1], | [[3, 5], | [[4, 9],
# [6, 8], | [7, 3], | [2, 4],
# [1, 6]], | [5, 7]], | [9, 2]])
b = b[np.arange(n), np.arange(n), :]
# Possibility 2
b = a[np.repeat(range(n), n-1), idx.ravel()]
# array([8, 1, 7, 3, 9, 2])
b = b.reshape(n, n-1)
Are there easier ways?

You can use np.take_along_axis here:
np.take_along_axis(a, idx, 1)
array([[8, 1],
[7, 3],
[9, 2]])
Or using broadcasting:
a[np.arange(a.shape[0])[:,None], idx]
array([[8, 1],
[7, 3],
[9, 2]])
Note that your using integer array indexing here, you need to specify over which axis and rows you want to index using idx.

Related

Comparing 2-dimensional numpy array in python

I want to comparing 2 values in a 2-dimensional numpy array. The array is as follows:
a = [[1, 3, 5],
[4, 8, 1]]
I want to comparing [1, 3, 5] with [4, 8, 1] with a greater value into 1 group.
The result I want is like this:
a1 = [4, 8, 5]
a2 = [1, 3, 1]
How could the code be written in python?
You can use np.sort on axis 0 (column-wise). Reverse the order using [::-1] to get them in descending order
>>> np.sort(a, axis = 0)[::-1]
array([[4, 8, 5],
[1, 3, 1]])
Since you only have 2 rows you can do this:
a = np.array([[1, 3, 5],
[4, 8, 1]])
idx = np.greater(*a)
a1 = a[idx.astype(int),np.arange(3)]
a2 = a[~idx.astype(int),np.arange(3)]

Changing value of element in 2D array in Python [duplicate]

This question already has an answer here:
Python change element in array [duplicate]
(1 answer)
Closed 2 years ago.
how do I change the value of 2d array without knowing its index?
Code:
array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in array:
for col in row:
if col == 2:
??????????? #this is what im looking for
Try enumerate() in both for loops, which returns index position and value. Then change directly in your array.
array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for ir, row in enumerate(array):
for ic, col in enumerate(row):
if col == 2:
array[ir][ic]= 99
You could use enumerate function:
for row in array:
for i,col in enumerate(row):
if col == 2:
row[i]=3
Try doing:
for row in array:
col[2] = #whatever you want to do
here is with numpy 2d array
import numpy as np
array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
array2d = np.array(array)
array2d
Out[1]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# Here case if you know or column and/or row
array2d[:,2] = 0 # here is you 'i'..for example set column 2 to 0
array2d
Out[2]:
array([[1, 2, 0],
[4, 5, 0],
[7, 8, 0]])
# Here case if you know condition, for example value '8' -> '88'
array2d[np.where(array2d ==8)] = 88
array2d
Out[3]:
array([[ 1, 2, 0],
[ 4, 5, 0],
[ 7, 88, 0]])

how to get the index of the subarray in pytorch?

a and b are torch tensor No repeating elements
a shape is [n,2] like:
[[1,2]
[2,3]
[4,6]
...]
b is[m,2] like:
[[1,2]
[4,6]
....
]
how to get the index of b in a, example:
a = [[1,2]
[2,4]
[6,7]
]
b = [[1,2]
[6,7]]
the index should be (0,3), we can use gpu,
I can think of the following trick that can work for you.
Since we have two tensors with different numbers of rows (n and m), first we transform them into the same shape (m x n x 2) and then subtract. If two rows match, then after subtraction, the entire row will be zero. Then, we need to identify the indices of those rows.
n = a.shape[0] # 3
m = b.shape[0] # 2
_a = a.unsqueeze(0).repeat(m, 1, 1) # m x n x 2
_b = b.unsqueeze(1).repeat(1, n, 1) # m x n x 2
match = (_a - _b).sum(-1) # m x n
indices = (match == 0).nonzero()
if indices.nelement() > 0: # empty tensor check
row_indices = indices[:, 1]
else:
row_indices = []
print(row_indices)
Sample Input/Output
Example 1
a = torch.tensor([[1, 2], [2, 4], [6, 7]])
b = torch.tensor([[1, 2], [6, 7]])
tensor([0, 2])
Example 2
a = torch.tensor([[1, 2], [2, 4], [6, 7]])
b = torch.tensor([[1, 3], [6, 7]])
tensor([2])
Example 3
a = torch.tensor([[1, 2], [2, 4], [6, 7]])
b = torch.tensor([[1, 2], [6, 5], [8, 9]])
tensor([0])
Example 4
a = torch.tensor([[1, 2], [2, 4], [6, 7]])
b = torch.tensor([[1, 3], [6, 5], [8, 9]])
[]
Here #jpp 's, numpy solution is almost your answer after this
You just need to get indices using nonzero and flatten tensor using flatten to get expected shape.
a = torch.tensor([[1, 2], [2, 4], [6, 7]])
b = torch.tensor([[1, 2], [6, 7]])
(a[:, None] == b).all(-1).any(-1).nonzero().flatten()
tensor([0, 2])

Python numpy Indexing multidimensional array [duplicate]

This question already has answers here:
Indexing one array by another in numpy
(4 answers)
Closed 4 years ago.
For each row of y I would like to get element whose indexes are specified in m.
>>> y = np.arange(15).reshape(3,5)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
>>> m = np.array([[0, 1], [1, 2], [2, 3]])
Expected output:
[[0, 1]
[6, 7]
[12, 13]]
Solution with for cycle
>>> np.stack([y[i, cols] for i, cols in enumerate(m)])
Is there a way how to do it without a for cycle?
Using values from one array as index from another is called 'fancy indexing', however that indexing operation will be repeated for all rows:
y = numpy.arange(15).reshape(3,5)
y[:, [0, 2, 3]]
# array([[ 0, 2, 3],
# [ 5, 7, 8],
# [10, 12, 13]])
If you want to individually "use one index value per row", you need to give that row-to-index relation as another index:
y[[0, 1, 2], [0, 2, 3]]
# array([ 0, 7, 13])
Since your index array m is 2D, you need to tell NumPy which of these two dimension in m corresponds to your row index. You do this by adding another empty axis to the ascending index, (keyword: broadcasting), and you get
y = numpy.arange(15).reshape(3,5)
m = numpy.array([[0, 1], [1, 2], [2, 3]])
y[numpy.arange(len(m))[:, None], m]
# array([[ 0, 1],
# [ 6, 7],
# [12, 13]])
One line, although not much nicer than your own proposal using the for loop:
y[..., m][np.identity(3, dtype=bool)]
Though it will give you some insights in numpy indexing.

Search Numpy array with multiple values

I have numpy 2d array having duplicate values.
I am searching the array like this.
In [104]: import numpy as np
In [105]: array = np.array
In [106]: a = array([[1, 2, 3],
...: [1, 2, 3],
...: [2, 5, 6],
...: [3, 8, 9],
...: [4, 8, 9],
...: [4, 2, 3],
...: [5, 2, 3])
In [107]: num_list = [1, 4, 5]
In [108]: for i in num_list :
...: print(a[np.where(a[:,0] == num_list)])
...:
[[1 2 3]
[1 2 3]]
[[4 8 9]
[4 2 3]]
[[5 2 3]]
The input is list having number similar to column 0 values.
The end result I want is the resulting rows in any format like array, list or tuple for example
array([[1, 2, 3],
[1, 2, 3],
[4, 8, 9],
[4, 2, 3],
[5, 2, 3]])
My code works fine but doesn't seem pythonic. Is there any better searching strategy with multiple values?
like a[np.where(a[:,0] == l)] where only one time lookup is done to get all the values.
my real array is large
Approach #1 : Using np.in1d -
a[np.in1d(a[:,0], num_list)]
Approach #2 : Using np.searchsorted -
num_arr = np.sort(num_list) # Sort num_list and get as array
# Get indices of occurrences of first column in num_list
idx = np.searchsorted(num_arr, a[:,0])
# Take care of out of bounds cases
idx[idx==len(num_arr)] = 0
out = a[a[:,0] == num_arr[idx]]
You can do
a[numpy.in1d(a[:, 0], num_list), :]

Categories

Resources