How do I make an ordered matrix in Python?
Question:
I have values p1,p2,p3,...
and phi_1,phi_2,phi_3....
and I’m looking to make a grid/matrix that looks something like
(p1,phi_1) (p2,phi_1)
(p1,phi_2) (p2,phi_2) . . .
(p1,phi_3) (p2,phi_3)
.
.
.
Is there any way to do this in a non-clunky manner?
In terms of ordering things I only really know how to to do things like
grid=np.array([[pj[i], phij[i]] for i in range(len(pj))])
which gives me
(p1,phi1)
(p2,phi_2)
.
.
.
I’m not really experienced enough to do anything else and I’m not sure how to google this!
Answers:
a = ["p1", "p2", "p3"]
b = ["phi1", "phi2", "phi3"]
result = [ [(x,y) for x in a] for y in b]
for row in result:
print(row)
pj = ['p1','p2','p3']
phij = ['phi_1','phi_2','phi_3']
grid = []
for phi in phij:
grid.append([(p,phi) for p in pj])
You can see a solution here.
import numpy as np;
arr1 = ['p1','p2','p3','p4']
arr2 = ['phi_1','phi_2','phi_3','phi_4']
arr3 = np.transpose([np.tile(arr1, len(arr2)), np.repeat(arr2, len(arr1))])
print(arr3)
You can read more about it here.
Using numpy to build an array of all combinations of two arrays
tl;dr: my one-liner is res = np.stack(np.meshgrid(p, phi), axis=2)
, if p
and phi
are two arrays of values.
I obviously did not understand the question the same way others did. But just in case my interpretation is the correct one: I think what you want is almost what meshgrid
does.
Example
p=np.array([1,2,3,4])
phi=np.array([10,20,30]) # Just to add some difficulty, not the same size
gr_p, gr_phi = np.meshgrid(p, phi)
produces 2 3×4 arrays. One with p
values: on each line, we have p1, p2, p3…
another with phi
values: 1st line with phi1, phi1, phi1, … second line with phi2, phi2, phi2, …
So what you want is a single 3×4 array, made of pairs taken from those 2 arrays (so a 2D array of pairs, instead of a pair of 2D array).
I really can’t see why you would insist on having a 2D numpy array of python pair (that is a numpy antipattern. It makes the numpy array an array of object, and you loose almost all vectorization force of numpy). So I suggest to build a 3D array, whose last axis is of size 2.
(It it were a 2D array of pairs, then arr[i,j][0]
would be p[j]
and arr[i,j][1]
phi[i]
. With the 3D array of values, it is arr[i,j,0]
and arr[i,j,1]
that are those values. And arr[i,j,0]
/arr[i,j,1]
can also be called arr[i,j][0]
, arr[i,j][1]
anyway. So really can’t see any reason why the last axis should be replaced by a tuple).
So to build such an array of pairs
aka 3d array, we can just stack the 2 arrays returned by meshgrid.
p=np.array([1,2,3,4])
phi=np.array([10,20,30]) # Just to add some difficulty, not the same size
res = np.stack(np.meshgrid(p, phi), axis=2)
res
here is exactly what you want, I think.
res[1,2]
for example is array([3,20])
(you expected (3,20)
, again, no advantage to keep it as tuple)
In this example, res is
array([[[ 1, 10], [ 2, 10], [ 3, 10], [ 4, 10]],
[[ 1, 20], [ 2, 20], [ 3, 20], [ 4, 20]],
[[ 1, 30], [ 2, 30], [ 3, 30], [ 4, 30]]])
Note: it works also if p
and phi
are arrays of strings, at others seemed to have understood anyway, so after all my answer is not that dependent from my interpretation.
Alternatively, you could try this product function from itertools module:
It can be used conveniently to create "cartesian product, equivalent to a nested for-loop"
from itertools import product
# lst1, list2 = ['hi', 'hii', 'hiii']
result = list(product(lst1, lst2))
# [('p1', 'hi'), ('p1', 'hii'), ('p1', 'hiii'), ('p2', 'hi'), ('p2', 'hii'), ('p2', 'hiii'), ('p3', 'hi'), ('p3', 'hii'), ('p3', 'hiii')]
I have values p1,p2,p3,...
and phi_1,phi_2,phi_3....
and I’m looking to make a grid/matrix that looks something like
(p1,phi_1) (p2,phi_1)
(p1,phi_2) (p2,phi_2) . . .
(p1,phi_3) (p2,phi_3)
.
.
.
Is there any way to do this in a non-clunky manner?
In terms of ordering things I only really know how to to do things like
grid=np.array([[pj[i], phij[i]] for i in range(len(pj))])
which gives me
(p1,phi1)
(p2,phi_2)
.
.
.
I’m not really experienced enough to do anything else and I’m not sure how to google this!
a = ["p1", "p2", "p3"]
b = ["phi1", "phi2", "phi3"]
result = [ [(x,y) for x in a] for y in b]
for row in result:
print(row)
pj = ['p1','p2','p3']
phij = ['phi_1','phi_2','phi_3']
grid = []
for phi in phij:
grid.append([(p,phi) for p in pj])
You can see a solution here.
import numpy as np;
arr1 = ['p1','p2','p3','p4']
arr2 = ['phi_1','phi_2','phi_3','phi_4']
arr3 = np.transpose([np.tile(arr1, len(arr2)), np.repeat(arr2, len(arr1))])
print(arr3)
You can read more about it here.
Using numpy to build an array of all combinations of two arrays
tl;dr: my one-liner is res = np.stack(np.meshgrid(p, phi), axis=2)
, if p
and phi
are two arrays of values.
I obviously did not understand the question the same way others did. But just in case my interpretation is the correct one: I think what you want is almost what meshgrid
does.
Example
p=np.array([1,2,3,4])
phi=np.array([10,20,30]) # Just to add some difficulty, not the same size
gr_p, gr_phi = np.meshgrid(p, phi)
produces 2 3×4 arrays. One with p
values: on each line, we have p1, p2, p3…
another with phi
values: 1st line with phi1, phi1, phi1, … second line with phi2, phi2, phi2, …
So what you want is a single 3×4 array, made of pairs taken from those 2 arrays (so a 2D array of pairs, instead of a pair of 2D array).
I really can’t see why you would insist on having a 2D numpy array of python pair (that is a numpy antipattern. It makes the numpy array an array of object, and you loose almost all vectorization force of numpy). So I suggest to build a 3D array, whose last axis is of size 2.
(It it were a 2D array of pairs, then arr[i,j][0]
would be p[j]
and arr[i,j][1]
phi[i]
. With the 3D array of values, it is arr[i,j,0]
and arr[i,j,1]
that are those values. And arr[i,j,0]
/arr[i,j,1]
can also be called arr[i,j][0]
, arr[i,j][1]
anyway. So really can’t see any reason why the last axis should be replaced by a tuple).
So to build such an array of pairs
aka 3d array, we can just stack the 2 arrays returned by meshgrid.
p=np.array([1,2,3,4])
phi=np.array([10,20,30]) # Just to add some difficulty, not the same size
res = np.stack(np.meshgrid(p, phi), axis=2)
res
here is exactly what you want, I think.
res[1,2]
for example is array([3,20])
(you expected (3,20)
, again, no advantage to keep it as tuple)
In this example, res is
array([[[ 1, 10], [ 2, 10], [ 3, 10], [ 4, 10]],
[[ 1, 20], [ 2, 20], [ 3, 20], [ 4, 20]],
[[ 1, 30], [ 2, 30], [ 3, 30], [ 4, 30]]])
Note: it works also if p
and phi
are arrays of strings, at others seemed to have understood anyway, so after all my answer is not that dependent from my interpretation.
Alternatively, you could try this product function from itertools module:
It can be used conveniently to create "cartesian product, equivalent to a nested for-loop"
from itertools import product
# lst1, list2 = ['hi', 'hii', 'hiii']
result = list(product(lst1, lst2))
# [('p1', 'hi'), ('p1', 'hii'), ('p1', 'hiii'), ('p2', 'hi'), ('p2', 'hii'), ('p2', 'hiii'), ('p3', 'hi'), ('p3', 'hii'), ('p3', 'hiii')]