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!

Asked By: Melissa Ewing

||

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)
Answered By: ashish singh
pj = ['p1','p2','p3']
phij = ['phi_1','phi_2','phi_3']
grid = []
for phi in phij:
    grid.append([(p,phi) for p in pj])
Answered By: Kurt

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

Answered By: Fakipo

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.

Answered By: chrslg

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')]
Answered By: Daniel Hao
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.