Numpy: Efficient way to convert indices of a square matrix to its upper triangular indices

Clash Royale CLAN TAG#URR8PPP
up vote
6
down vote
favorite
Question: given a tuple of index, return its order in upper triangular indices. Here is an example:
Suppose we have a square matrix A of shape (3, 3).
A has 6 upper triangular indices, namely, (0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2).
Now I know an element at index (1, 2), which is a index belongs to the upper triangular part of A. I would like to return 4 (which means it is the 5th element in all upper triangular indices.)
Any ideas on how to do that in general?
Best,
Zhihao
python numpy matrix
add a comment |
up vote
6
down vote
favorite
Question: given a tuple of index, return its order in upper triangular indices. Here is an example:
Suppose we have a square matrix A of shape (3, 3).
A has 6 upper triangular indices, namely, (0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2).
Now I know an element at index (1, 2), which is a index belongs to the upper triangular part of A. I would like to return 4 (which means it is the 5th element in all upper triangular indices.)
Any ideas on how to do that in general?
Best,
Zhihao
python numpy matrix
More general, if I have a list of indices, do we have a function to convert them to triu indices together [return a list/array of converted results]?
– Zhihao Cui
2 hours ago
add a comment |
up vote
6
down vote
favorite
up vote
6
down vote
favorite
Question: given a tuple of index, return its order in upper triangular indices. Here is an example:
Suppose we have a square matrix A of shape (3, 3).
A has 6 upper triangular indices, namely, (0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2).
Now I know an element at index (1, 2), which is a index belongs to the upper triangular part of A. I would like to return 4 (which means it is the 5th element in all upper triangular indices.)
Any ideas on how to do that in general?
Best,
Zhihao
python numpy matrix
Question: given a tuple of index, return its order in upper triangular indices. Here is an example:
Suppose we have a square matrix A of shape (3, 3).
A has 6 upper triangular indices, namely, (0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2).
Now I know an element at index (1, 2), which is a index belongs to the upper triangular part of A. I would like to return 4 (which means it is the 5th element in all upper triangular indices.)
Any ideas on how to do that in general?
Best,
Zhihao
python numpy matrix
python numpy matrix
edited 2 hours ago
RafaelC
25k82547
25k82547
asked 2 hours ago
Zhihao Cui
554
554
More general, if I have a list of indices, do we have a function to convert them to triu indices together [return a list/array of converted results]?
– Zhihao Cui
2 hours ago
add a comment |
More general, if I have a list of indices, do we have a function to convert them to triu indices together [return a list/array of converted results]?
– Zhihao Cui
2 hours ago
More general, if I have a list of indices, do we have a function to convert them to triu indices together [return a list/array of converted results]?
– Zhihao Cui
2 hours ago
More general, if I have a list of indices, do we have a function to convert them to triu indices together [return a list/array of converted results]?
– Zhihao Cui
2 hours ago
add a comment |
6 Answers
6
active
oldest
votes
up vote
2
down vote
accepted
One can write down the explicit formula:
def utr_idx(N, i, j):
return (2*N+1-i)*i//2 + j-i
Demo:
>>> N = 127
>>> X = np.transpose(np.triu_indices(N))
>>> utr_idx(N, *X[2123])
2123
I just realized it lol
– Zhihao Cui
1 hour ago
add a comment |
up vote
2
down vote
IIUC, you can get the indexes using itertools combinations with replacement
>>> ind = tuple(itertools.combinations_with_replacement(range(3),2))
((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
To retrieve the index, just use index method
>>> ind.index((1,2))
4
add a comment |
up vote
2
down vote
You could use np.triu_indices and a dictionary:
import numpy as np
iu1 = np.triu_indices(3)
table = (i, j): c for c, (i, j) in enumerate(zip(*iu1))
print(table[(1, 2)])
Output
4
add a comment |
up vote
2
down vote
For an n×n matrix, the (i, j)-th item of the upper triangle is the i×(2×n-i+1)/2+j-i-th element of the matrix.
We can also do the math in reverse and obtain the (i, j) element for the k-th element with:
i = ⌊(-√((2n+1)2-8k)+2n+1)/2⌋ and j = k+i-i×(2×n-i+1)/2
So for example:
from math import floor, sqrt
def coor_to_idx(n, i, j):
return i*(2*n-i+1)//2+j-i
def idx_to_coor(n, k):
i = floor((-sqrt((2*n+1)*(2*n+1)-8*k)+2*n+1)/2)
j = k + i - i*(2*n-i+1)//2
return i, j
For example:
>>> [idx_to_coor(4, i) for i in range(10)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
>>> [coor_to_idx(4, i, j) for i in range(4) for j in range(i, 4)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Given the numbers are not huge (well if these are huge, calculations are no longer done in constant time), we can thus calculate the k-th coordinate in O(1), for example:
>>> idx_to_coor(1234567, 123456789)
(100, 5139)
which is equivalent to obtaining it through enumeration:
>>> next(islice(((i, j) for i in range(1234567) for j in range(i, 1234567)), 123456789, None))
(100, 5139)
Here converting indices to a coordinate can also have, for large numbers, some rounding errors due to floating point imprecision.
add a comment |
up vote
1
down vote
Similar to @DanielMesejo, you can use np.triu_indices with either argwhere or nonzero:
my_index = (1,2)
>>> np.nonzero((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
(array([4]),)
>>> np.argwhere((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
array([[4]])
Explanation:
np.stack(np.triu_indices(3), axis=1) gives you the indices of your upper triangle in order:
array([[0, 0],
[0, 1],
[0, 2],
[1, 1],
[1, 2],
[2, 2]])
So all you have to do is find where it matches [1,2] (which you can do with the == operator and all)
add a comment |
up vote
1
down vote
Constructing upper indices would be costly. We can directly get the corresponding index like so -
def triu_index(N, x, y):
# Get index corresponding to (x,y) in upper triangular list
idx = np.r_[0,np.arange(N,1,-1).cumsum()]
return idx[x]+y-x
Sample run -
In [271]: triu_index(N=3, x=1, y=2)
Out[271]: 4
add a comment |
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
One can write down the explicit formula:
def utr_idx(N, i, j):
return (2*N+1-i)*i//2 + j-i
Demo:
>>> N = 127
>>> X = np.transpose(np.triu_indices(N))
>>> utr_idx(N, *X[2123])
2123
I just realized it lol
– Zhihao Cui
1 hour ago
add a comment |
up vote
2
down vote
accepted
One can write down the explicit formula:
def utr_idx(N, i, j):
return (2*N+1-i)*i//2 + j-i
Demo:
>>> N = 127
>>> X = np.transpose(np.triu_indices(N))
>>> utr_idx(N, *X[2123])
2123
I just realized it lol
– Zhihao Cui
1 hour ago
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
One can write down the explicit formula:
def utr_idx(N, i, j):
return (2*N+1-i)*i//2 + j-i
Demo:
>>> N = 127
>>> X = np.transpose(np.triu_indices(N))
>>> utr_idx(N, *X[2123])
2123
One can write down the explicit formula:
def utr_idx(N, i, j):
return (2*N+1-i)*i//2 + j-i
Demo:
>>> N = 127
>>> X = np.transpose(np.triu_indices(N))
>>> utr_idx(N, *X[2123])
2123
answered 1 hour ago
Paul Panzer
28.3k21138
28.3k21138
I just realized it lol
– Zhihao Cui
1 hour ago
add a comment |
I just realized it lol
– Zhihao Cui
1 hour ago
I just realized it lol
– Zhihao Cui
1 hour ago
I just realized it lol
– Zhihao Cui
1 hour ago
add a comment |
up vote
2
down vote
IIUC, you can get the indexes using itertools combinations with replacement
>>> ind = tuple(itertools.combinations_with_replacement(range(3),2))
((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
To retrieve the index, just use index method
>>> ind.index((1,2))
4
add a comment |
up vote
2
down vote
IIUC, you can get the indexes using itertools combinations with replacement
>>> ind = tuple(itertools.combinations_with_replacement(range(3),2))
((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
To retrieve the index, just use index method
>>> ind.index((1,2))
4
add a comment |
up vote
2
down vote
up vote
2
down vote
IIUC, you can get the indexes using itertools combinations with replacement
>>> ind = tuple(itertools.combinations_with_replacement(range(3),2))
((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
To retrieve the index, just use index method
>>> ind.index((1,2))
4
IIUC, you can get the indexes using itertools combinations with replacement
>>> ind = tuple(itertools.combinations_with_replacement(range(3),2))
((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
To retrieve the index, just use index method
>>> ind.index((1,2))
4
answered 1 hour ago
RafaelC
25k82547
25k82547
add a comment |
add a comment |
up vote
2
down vote
You could use np.triu_indices and a dictionary:
import numpy as np
iu1 = np.triu_indices(3)
table = (i, j): c for c, (i, j) in enumerate(zip(*iu1))
print(table[(1, 2)])
Output
4
add a comment |
up vote
2
down vote
You could use np.triu_indices and a dictionary:
import numpy as np
iu1 = np.triu_indices(3)
table = (i, j): c for c, (i, j) in enumerate(zip(*iu1))
print(table[(1, 2)])
Output
4
add a comment |
up vote
2
down vote
up vote
2
down vote
You could use np.triu_indices and a dictionary:
import numpy as np
iu1 = np.triu_indices(3)
table = (i, j): c for c, (i, j) in enumerate(zip(*iu1))
print(table[(1, 2)])
Output
4
You could use np.triu_indices and a dictionary:
import numpy as np
iu1 = np.triu_indices(3)
table = (i, j): c for c, (i, j) in enumerate(zip(*iu1))
print(table[(1, 2)])
Output
4
answered 1 hour ago
Daniel Mesejo
7,0411821
7,0411821
add a comment |
add a comment |
up vote
2
down vote
For an n×n matrix, the (i, j)-th item of the upper triangle is the i×(2×n-i+1)/2+j-i-th element of the matrix.
We can also do the math in reverse and obtain the (i, j) element for the k-th element with:
i = ⌊(-√((2n+1)2-8k)+2n+1)/2⌋ and j = k+i-i×(2×n-i+1)/2
So for example:
from math import floor, sqrt
def coor_to_idx(n, i, j):
return i*(2*n-i+1)//2+j-i
def idx_to_coor(n, k):
i = floor((-sqrt((2*n+1)*(2*n+1)-8*k)+2*n+1)/2)
j = k + i - i*(2*n-i+1)//2
return i, j
For example:
>>> [idx_to_coor(4, i) for i in range(10)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
>>> [coor_to_idx(4, i, j) for i in range(4) for j in range(i, 4)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Given the numbers are not huge (well if these are huge, calculations are no longer done in constant time), we can thus calculate the k-th coordinate in O(1), for example:
>>> idx_to_coor(1234567, 123456789)
(100, 5139)
which is equivalent to obtaining it through enumeration:
>>> next(islice(((i, j) for i in range(1234567) for j in range(i, 1234567)), 123456789, None))
(100, 5139)
Here converting indices to a coordinate can also have, for large numbers, some rounding errors due to floating point imprecision.
add a comment |
up vote
2
down vote
For an n×n matrix, the (i, j)-th item of the upper triangle is the i×(2×n-i+1)/2+j-i-th element of the matrix.
We can also do the math in reverse and obtain the (i, j) element for the k-th element with:
i = ⌊(-√((2n+1)2-8k)+2n+1)/2⌋ and j = k+i-i×(2×n-i+1)/2
So for example:
from math import floor, sqrt
def coor_to_idx(n, i, j):
return i*(2*n-i+1)//2+j-i
def idx_to_coor(n, k):
i = floor((-sqrt((2*n+1)*(2*n+1)-8*k)+2*n+1)/2)
j = k + i - i*(2*n-i+1)//2
return i, j
For example:
>>> [idx_to_coor(4, i) for i in range(10)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
>>> [coor_to_idx(4, i, j) for i in range(4) for j in range(i, 4)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Given the numbers are not huge (well if these are huge, calculations are no longer done in constant time), we can thus calculate the k-th coordinate in O(1), for example:
>>> idx_to_coor(1234567, 123456789)
(100, 5139)
which is equivalent to obtaining it through enumeration:
>>> next(islice(((i, j) for i in range(1234567) for j in range(i, 1234567)), 123456789, None))
(100, 5139)
Here converting indices to a coordinate can also have, for large numbers, some rounding errors due to floating point imprecision.
add a comment |
up vote
2
down vote
up vote
2
down vote
For an n×n matrix, the (i, j)-th item of the upper triangle is the i×(2×n-i+1)/2+j-i-th element of the matrix.
We can also do the math in reverse and obtain the (i, j) element for the k-th element with:
i = ⌊(-√((2n+1)2-8k)+2n+1)/2⌋ and j = k+i-i×(2×n-i+1)/2
So for example:
from math import floor, sqrt
def coor_to_idx(n, i, j):
return i*(2*n-i+1)//2+j-i
def idx_to_coor(n, k):
i = floor((-sqrt((2*n+1)*(2*n+1)-8*k)+2*n+1)/2)
j = k + i - i*(2*n-i+1)//2
return i, j
For example:
>>> [idx_to_coor(4, i) for i in range(10)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
>>> [coor_to_idx(4, i, j) for i in range(4) for j in range(i, 4)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Given the numbers are not huge (well if these are huge, calculations are no longer done in constant time), we can thus calculate the k-th coordinate in O(1), for example:
>>> idx_to_coor(1234567, 123456789)
(100, 5139)
which is equivalent to obtaining it through enumeration:
>>> next(islice(((i, j) for i in range(1234567) for j in range(i, 1234567)), 123456789, None))
(100, 5139)
Here converting indices to a coordinate can also have, for large numbers, some rounding errors due to floating point imprecision.
For an n×n matrix, the (i, j)-th item of the upper triangle is the i×(2×n-i+1)/2+j-i-th element of the matrix.
We can also do the math in reverse and obtain the (i, j) element for the k-th element with:
i = ⌊(-√((2n+1)2-8k)+2n+1)/2⌋ and j = k+i-i×(2×n-i+1)/2
So for example:
from math import floor, sqrt
def coor_to_idx(n, i, j):
return i*(2*n-i+1)//2+j-i
def idx_to_coor(n, k):
i = floor((-sqrt((2*n+1)*(2*n+1)-8*k)+2*n+1)/2)
j = k + i - i*(2*n-i+1)//2
return i, j
For example:
>>> [idx_to_coor(4, i) for i in range(10)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
>>> [coor_to_idx(4, i, j) for i in range(4) for j in range(i, 4)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Given the numbers are not huge (well if these are huge, calculations are no longer done in constant time), we can thus calculate the k-th coordinate in O(1), for example:
>>> idx_to_coor(1234567, 123456789)
(100, 5139)
which is equivalent to obtaining it through enumeration:
>>> next(islice(((i, j) for i in range(1234567) for j in range(i, 1234567)), 123456789, None))
(100, 5139)
Here converting indices to a coordinate can also have, for large numbers, some rounding errors due to floating point imprecision.
edited 1 hour ago
answered 1 hour ago
Willem Van Onsem
138k16129219
138k16129219
add a comment |
add a comment |
up vote
1
down vote
Similar to @DanielMesejo, you can use np.triu_indices with either argwhere or nonzero:
my_index = (1,2)
>>> np.nonzero((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
(array([4]),)
>>> np.argwhere((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
array([[4]])
Explanation:
np.stack(np.triu_indices(3), axis=1) gives you the indices of your upper triangle in order:
array([[0, 0],
[0, 1],
[0, 2],
[1, 1],
[1, 2],
[2, 2]])
So all you have to do is find where it matches [1,2] (which you can do with the == operator and all)
add a comment |
up vote
1
down vote
Similar to @DanielMesejo, you can use np.triu_indices with either argwhere or nonzero:
my_index = (1,2)
>>> np.nonzero((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
(array([4]),)
>>> np.argwhere((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
array([[4]])
Explanation:
np.stack(np.triu_indices(3), axis=1) gives you the indices of your upper triangle in order:
array([[0, 0],
[0, 1],
[0, 2],
[1, 1],
[1, 2],
[2, 2]])
So all you have to do is find where it matches [1,2] (which you can do with the == operator and all)
add a comment |
up vote
1
down vote
up vote
1
down vote
Similar to @DanielMesejo, you can use np.triu_indices with either argwhere or nonzero:
my_index = (1,2)
>>> np.nonzero((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
(array([4]),)
>>> np.argwhere((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
array([[4]])
Explanation:
np.stack(np.triu_indices(3), axis=1) gives you the indices of your upper triangle in order:
array([[0, 0],
[0, 1],
[0, 2],
[1, 1],
[1, 2],
[2, 2]])
So all you have to do is find where it matches [1,2] (which you can do with the == operator and all)
Similar to @DanielMesejo, you can use np.triu_indices with either argwhere or nonzero:
my_index = (1,2)
>>> np.nonzero((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
(array([4]),)
>>> np.argwhere((np.stack(np.triu_indices(3), axis=1) == my_index).all(1))
array([[4]])
Explanation:
np.stack(np.triu_indices(3), axis=1) gives you the indices of your upper triangle in order:
array([[0, 0],
[0, 1],
[0, 2],
[1, 1],
[1, 2],
[2, 2]])
So all you have to do is find where it matches [1,2] (which you can do with the == operator and all)
answered 1 hour ago
sacul
25.9k41638
25.9k41638
add a comment |
add a comment |
up vote
1
down vote
Constructing upper indices would be costly. We can directly get the corresponding index like so -
def triu_index(N, x, y):
# Get index corresponding to (x,y) in upper triangular list
idx = np.r_[0,np.arange(N,1,-1).cumsum()]
return idx[x]+y-x
Sample run -
In [271]: triu_index(N=3, x=1, y=2)
Out[271]: 4
add a comment |
up vote
1
down vote
Constructing upper indices would be costly. We can directly get the corresponding index like so -
def triu_index(N, x, y):
# Get index corresponding to (x,y) in upper triangular list
idx = np.r_[0,np.arange(N,1,-1).cumsum()]
return idx[x]+y-x
Sample run -
In [271]: triu_index(N=3, x=1, y=2)
Out[271]: 4
add a comment |
up vote
1
down vote
up vote
1
down vote
Constructing upper indices would be costly. We can directly get the corresponding index like so -
def triu_index(N, x, y):
# Get index corresponding to (x,y) in upper triangular list
idx = np.r_[0,np.arange(N,1,-1).cumsum()]
return idx[x]+y-x
Sample run -
In [271]: triu_index(N=3, x=1, y=2)
Out[271]: 4
Constructing upper indices would be costly. We can directly get the corresponding index like so -
def triu_index(N, x, y):
# Get index corresponding to (x,y) in upper triangular list
idx = np.r_[0,np.arange(N,1,-1).cumsum()]
return idx[x]+y-x
Sample run -
In [271]: triu_index(N=3, x=1, y=2)
Out[271]: 4
answered 1 hour ago
Divakar
151k1475166
151k1475166
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53233695%2fnumpy-efficient-way-to-convert-indices-of-a-square-matrix-to-its-upper-triangul%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password

More general, if I have a list of indices, do we have a function to convert them to triu indices together [return a list/array of converted results]?
– Zhihao Cui
2 hours ago