0

I have a 2D array whose first 3 columns represent x,y,z coordinates and the last column contains some data. I am trying to create a 3D array using the data from the last column. The code I have written for this has 3 for loops. Would appreciate it if anyone can suggest improvements to this code or has an alternate better way of arriving at the same solution.

tempData = np.loadtxt(cwd+'/T_t0-t20.txt', comments='%', usecols=(0,1,2,3))   
x = np.sort(np.unique(tempData[:, 0]))
y = np.sort(np.unique(tempData[:, 1]))
z = np.sort(np.unique(tempData[:, 2]))
temp = np.zeros((len(x),len(y),len(z)))
for i in range(len(x)):
    for j in range(len(y)):
        for k in range(len(z)):            
            xind = np.where(tempData[:,0]==x[i])[0]
            yind = np.where(tempData[:,1]==y[j])[0]
            zind = np.where(tempData[:,2]==z[k])[0]                
            Tind = np.intersect1d(np.intersect1d(xind, yind), zind)[0]                          
            temp[i,j,k] = tempData[:,3][Tind]

Here is an example input 2D array (tempData):

[[ 0.0000e+00 -2.1429e-02  0.0000e+00  8.5963e+02]
 [ 2.0202e-02 -2.1429e-02  0.0000e+00  8.1597e+02]
 [ 4.0404e-02 -2.1429e-02  0.0000e+00  7.7315e+02]
 [ 0.0000e+00  0.0000e+00  0.0000e+00  9.1180e+02]
 [ 2.0202e-02  0.0000e+00  0.0000e+00  8.5293e+02]
 [ 4.0404e-02  0.0000e+00  0.0000e+00  7.9282e+02]
 [ 0.0000e+00  2.1429e-02  0.0000e+00  8.2700e+02]
 [ 2.0202e-02  2.1429e-02  0.0000e+00  8.1224e+02]
 [ 4.0404e-02  2.1429e-02  0.0000e+00  7.7315e+02]
 [ 0.0000e+00 -2.1429e-02 -2.2222e-02  8.5946e+02]
 [ 2.0202e-02 -2.1429e-02 -2.2222e-02  8.1589e+02]
 [ 4.0404e-02 -2.1429e-02 -2.2222e-02  7.7315e+02]
 [ 0.0000e+00  0.0000e+00 -2.2222e-02  9.1153e+02]
 [ 2.0202e-02  0.0000e+00 -2.2222e-02  8.5278e+02]
 [ 4.0404e-02  0.0000e+00 -2.2222e-02  7.9278e+02]
 [ 0.0000e+00  2.1429e-02 -2.2222e-02  8.2689e+02]
 [ 2.0202e-02  2.1429e-02 -2.2222e-02  8.1216e+02]
 [ 4.0404e-02  2.1429e-02 -2.2222e-02  7.7315e+02]
 [ 0.0000e+00 -2.1429e-02 -4.4444e-02  8.3552e+02]
 [ 2.0202e-02 -2.1429e-02 -4.4444e-02  8.0395e+02]
 [ 4.0404e-02 -2.1429e-02 -4.4444e-02  7.7315e+02]
 [ 0.0000e+00  0.0000e+00 -4.4444e-02  8.7343e+02]
 [ 2.0202e-02  0.0000e+00 -4.4444e-02  8.3067e+02]
 [ 4.0404e-02  0.0000e+00 -4.4444e-02  7.8726e+02]
 [ 0.0000e+00  2.1429e-02 -4.4444e-02  8.1191e+02]
 [ 2.0202e-02  2.1429e-02 -4.4444e-02  8.0125e+02]
 [ 4.0404e-02  2.1429e-02 -4.4444e-02  7.7315e+02]]

And here's the expected output array (temp):

[[[835.52 859.46 859.63]
  [873.43 911.53 911.8 ]
  [811.91 826.89 827.  ]]

 [[803.95 815.89 815.97]
  [830.67 852.78 852.93]
  [801.25 812.16 812.24]]

 [[773.15 773.15 773.15]
  [787.26 792.78 792.82]
  [773.15 773.15 773.15]]]
Dexter
  • 43
  • 5
  • 2
    Do you have an example input and an expected output? In general, you shouldnt be using three levels of for loops, it leads to slow code, instead you should use vectorized code - https://stackoverflow.com/questions/47755442/what-is-vectorization/47755634 – Tom McLean Apr 20 '21 at 14:39
  • `np.unique` says it returns sorted values. It can also return `indices` and `inverse indices`, which may let you skip the `np.nonzero`. But I haven't looked enough at your code to get a clear idea of what it's supposed to be doing, especially since you don't provide a small sample `tempData` array (and results); – hpaulj Apr 20 '21 at 15:47
  • 1
    If you look at answers to similar questions, you'll see that we 'prove' them with a small working example. I like to display intermediate results as well, so the OP can visualize what's going on (it also helps me when developing and testing the code). Your question is sorely missing any of that useful stuff. – hpaulj Apr 20 '21 at 15:50
  • @hpaulj: Thanks for pointing it out. I have edited the post to include example input and output arrays – Dexter Apr 21 '21 at 06:58

1 Answers1

0

I found a better (efficient) way using Numpy's lexsort. This avoids the for loops completly. Multi-column sorting is performed here, first along 'x', then along 'y' and then along 'z'. Here's the code:

x = np.sort(np.unique(tempData[:, 0]))
y = np.sort(np.unique(tempData[:, 1]))
z = np.sort(np.unique(tempData[:, 2]))
tempData = tempData[np.lexsort(np.transpose(tempData)[::-1])]
temp = np.array(tempData[:, 3]).reshape((len(x),len(y),len(z)))
Dexter
  • 43
  • 5