Search code examples
pythonnumpyreshape

Numpy: convert xyzV table to a grid


I have this text file I can read with numpy.loadtxt into a 2D array:

 X   Y   Z   V
-30 -15 -25  2
-29 -15 -25  2.1
-28 -15 -25  2.2
 .   .   .    .
 .   .   .    .
+29 -15 -25  2.1
+30 -15 -25 -2.0
-30 -14 -25  2   # now iterating X values while Y=-14
-29 -14 -25  2.1
-28  .   .   2.2
 .   .   .    .
 .   .   .    .
+29 -13 -25  2.1
+30 -13 -25 -2.0 # now iterating X values while Y=-13, and so on...
 .   .   .    .
 .   .   .    .
 .   .   .    .
 .   .   .    .

The ranges of X, Y and Z are not necessarily integers, and as illustrated above not the same in all axes. I want to create a grid out of this data, i.e to get arrays such that:

>>> np.shape(V)
(61,31,51)
>>> np.shape(x)
(61,)
>>> np.shape(y)
(31,)
>>> np.shape(z)
(51,)

I saw an almost identical question here, but its clear to see that the answer there rely on the fact that the X & Y columns contain integers starting from a known, and positive number.


Solution

  • Assuming the table is consistent with the repetition of X,Y & Z values, you can use np.unique and len to calculate the shape the resulting array should get. Here's a complete code that's working:

    import numpy as np
    
    table = np.loadtxt("potential.csv", delimeter=",", skiprows=1)
    x = np.unique(table[:,0])
    y = np.unique(table[:,1])
    z = np.unique(table[:,2])
    
    potential = np.zeros((len(x), len(y), len(z)))
    for i in range(len(z)):
        for j in range(len(y)):
            for k in range(len(x)):
                index = k + j*len(x)+ i*len(y)*len(x)
                potential[k,j,i] = table[index, 3]
    

    np.reshape doesn't fit in this case. To reach the correct index in the 1 dimensional array of table, you have to use the fact that Y values are changed after all X values were iterated. Hence we multiply j by the length of x. Same goes with Z indices in relationship with X and Y lengths.