python : extract submatrices from indices - python

I have a matrix and a list of indices for both dimensions.
A = [[1,2,3],[4,5,6],[7,8,9]]
idx = [1,3,4]
idy = [2,5,7]
What is the similar notation from Matlab doing A(idx,idy) in Python?

Here is my exmple:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
idx = [0, 1]
idy = [1, 2]
a = [[A[ix][iy] for iy in idy] for ix in idx]
print(a)
From:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
I am obtaining the submatrix according to my indexes idx and idy:
[
[2, 3],
[5, 6]
]
Please keep in mind that in python indexing start from 0 so giving the fact that here we have a 3x3 matrix the smallest index is 0 and the biggest is 2 for each row and column.
Is this what you are looking for? Please let me know.

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]

How would I 'move' up or down through a 2d array

For example you are given the array:
array = [[2, 1, 4],
[1, 3, 7],
[7, 1, 4]]
and want to print each vertical column as a separate list:
res1 = [2, 1, 7]
res2 = [1, 3, 1]
res3 = [4, 7, 4]
what would be the most efficient way to code this for any size 2d array?
If your 2D array is large and want lots of computation on it, better let numpy handle it
import numpy as np
array = np.array([[2, 1, 4],
[1, 3, 7],
[7, 1, 4]])
for col in array.T:
print(col)
for i in range(len(array[0])):
print("Row {} : {}".format(i+1, array[i]))
Output
Row 1 : [2, 1, 4]
Row 2 : [1, 3, 7]
Row 3 : [7, 1, 4]
You can use this code,
for x in range(len(array)):
print("Row",x+1,":",array[x])

Python - doing maths with a nested list

If I have a nested list, e.g. x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]], how can I calculate the difference between all of them? Let's called the lists inside x - A, B, and C. I want to calculate the difference of A from B & C, then B from A & C, then C from A & B, then put them in a list diff = [].
My problem is correctly indexing the numbers and using them to do maths with corresponding elements in other lists.
This is what I have so far:
for i in range(len(x)):
diff = []
for j in range(len(x)):
if x[i]!=x[j]:
a = x[i]
b = x[j]
for h in range(len(a)):
d = a[h] - b[h]
diff.append(d)
Essentially for the difference of A to B it is ([1-2] + [2-4] + [3-6])
I would like it to return: diff = [[diff(A,B), diff(A,C)], [diff(B,A), diff(B,C)], [diff(C,A), diff(C,B)]] with the correct differences between points.
Thanks in advance!
Your solution is actually not that far off. As Aniketh mentioned, one issue is your use of x[i] != x[j]. Since x[i] and x[j] are arrays, that will actually always evaluate to false.
The reason is that python will not do a useful comparison of arrays by default. It will just check if the array reference is the same. This is obviously not what you want, you are trying to see if the array is at the same index in x. For that use i !=j.
Though there are other solutions posted here, I'll add mine below because I already wrote it. It makes use of python's list comprehensions.
def pairwise_diff(x):
diff = []
for i in range(len(x)):
A = x[i]
for j in range(len(x)):
if i != j:
B = x[j]
assert len(A) == len(B)
item_diff = [A[i] - B[i] for i in range(len(A))]
diff.append(sum(item_diff))
# Take the answers and group them into arrays of length 2
return [diff[i : i + 2] for i in range(0, len(diff), 2)]
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
print(pairwise_diff(x))
This is one of those problems where it's really helpful to know a bit of Python's standard library — especially itertools.
For example to get the pairs of lists you want to operate on, you can reach for itertools.permutations
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
list(permutations(x, r=2))
This gives the pairs of lists your want:
[([1, 2, 3], [2, 4, 6]),
([1, 2, 3], [3, 5, 7]),
([2, 4, 6], [1, 2, 3]),
([2, 4, 6], [3, 5, 7]),
([3, 5, 7], [1, 2, 3]),
([3, 5, 7], [2, 4, 6])]
Now, if you could just group those by the first of each pair...itertools.groupby does just this.
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
list(list(g) for k, g in groupby(permutations(x, r=2), key=lambda p: p[0]))
Which produces a list of lists grouped by the first:
[[([1, 2, 3], [2, 4, 6]), ([1, 2, 3], [3, 5, 7])],
[([2, 4, 6], [1, 2, 3]), ([2, 4, 6], [3, 5, 7])],
[([3, 5, 7], [1, 2, 3]), ([3, 5, 7], [2, 4, 6])]]
Putting it all together, you can make a simple function that subtracts the lists the way you want and pass each pair in:
from itertools import permutations, groupby
def sum_diff(pairs):
return [sum(p - q for p, q in zip(*pair)) for pair in pairs]
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
# call sum_diff for each group of pairs
result = [sum_diff(g) for k, g in groupby(permutations(x, r=2), key=lambda p: p[0])]
# [[-6, -9], [6, -3], [9, 3]]
This reduces the problem to just a couple lines of code and will be performant on large lists. And, since you mentioned the difficulty in keeping indices straight, notice that this uses no indices in the code other than selecting the first element for grouping.
Here is the code I believe you're looking for. I will explain it below:
def diff(a, b):
total = 0
for i in range(len(a)):
total += a[i] - b[i]
return total
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
differences = []
for i in range(len(x)):
soloDiff = []
for j in range(len(x)):
if i != j:
soloDiff.append(diff(x[i],x[j]))
differences.append(soloDiff)
print(differences)
Output:
[[-6, -9], [6, -3], [9, 3]]
First off, in your explanation of your algorithm, you are making it very clear that you should use a function to calculate the differences between two lists since you will be using it repeatedly.
Your for loops start off fine, but you should have a second list to append diff to 3 times. Also, when you are checking for repeats you need to make sure that i != j, not x[i] != x[j]
Let me know if you have any other questions!!
this is the simplest solution i can think:
import numpy as np
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
x = np.array(x)
vectors = ['A','B','C']
for j in range(3):
for k in range(3):
if j!=k:
print(vectors[j],'-',vectors[k],'=', x[j]-x[k])
which will return
A - B = [-1 -2 -3]
A - C = [-2 -3 -4]
B - A = [1 2 3]
B - C = [-1 -1 -1]
C - A = [2 3 4]
C - B = [1 1 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.

Met with "Index Out of Range" when Trying to Transpose Matrix

I'm trying to figure out how to transpose a matrix with vectors that contain an unequal amount of elements.
I'm just learning to program and I'm currently working through the Python Tutorial and I'm stuck on an example listed in "Nested List Comprehensions" here: https://docs.python.org/3/tutorial/datastructures.html#nested-list-comprehensions.
Here is a very slight variation of example shown in the Python Tutorial:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
[[row[i] for row in matrix] for i in range(3)]
I decided to create my own solution for the example because I wanted the code to be a bit more dynamic, which was this:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
[[row[i] for row in matrix] for i in range(len(matrix))]
However, shortly after coming up with my solution I noticed there was a lot of ways it could still break and tried figuring out a solution that wouldn't break under any of the following scenarios:
# Scenario 1: Vectors of unequal length sizes.
matrix = [
[1, 2, 3, 4],
[5, 6, 7],
[8, 9, 10, 11]
# Scenario 2: len(vector) > len(matrix)
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8]
]
# Scenario 3: len(vector) < len(matrix)
matrix = [
[1, 2],
[3, 4],
[5, 6],
[7, 8]
]
If anyone can come up with a solution using nested list comprehensions that would be able to handle all 3 of these scenarios, I would greatly appreciate your help.
disclaimer: all of this assumes your rows are all of the same length (as should be for a matrix).
just a minor tweak will do:
[[row[i] for row in matrix] for i in range(len(matrix[0]))]
the point is to have i in the range of the length of the rows of you matrix len(matrix[0]) (i am using the first row here as it always should exist).
a more elegant way is using zip:
list(zip(*matrix))
although you will get tuples as rows. if you need lists you can do:
[list(row) for row in zip(*matrix1)]
This works for both equal and unequal row lengths by collapsing the sparse rows to the left:
[[row[i] for row in matrix if i < len(row)] for i in range(max(len(r) for r in matrix))]
So scenario 1
matrix = [
[1, 2, 3, 4],
[5, 6, 7],
[8, 9, 10, 11]]
becomes
[[1, 5, 8],
[2, 6, 9],
[3, 7, 10],
[4, 11]]

Categories