I want to create a large NumPy array (L) to hold the result of some operations. However, I can only compute one part of L at a time. Then, to have L, I need to create an array of zeros of shape L.shape, and fill it using these parts or subarrays. I'm currently able to do it, but in a very inefficient way.
If the shape of L is (x, y, z, a, b, c), then I'm creating a NumPy arrays of shape (x, y, z, 1, b, c) which correspond to the different parts of L, from part 0 to part a-1. I'm forced to create arrays of this particular shape due to the operations involved.
In order to fill the array of zeros, I'm creating one Pandas DataFrame per subarray (or part). Each dataframe contains the indices and the values of one subarray of shape (x, y, z, 1, b, c), like this:
index0 | index1 | index2 | index3 | index4 | index5 | value
------------------------------------------------------------
0 | 0 | 0 | 0 | 0 | 0 | 434.2
0 | 0 | 0 | 0 | 0 | 1 | 234.5
..., and so on.
Because of the shape (x, y, z, 1, b, c), index3 can only contain zeros. So, there's a change to make before the values can be inserted at the right index of L: the column at index3 will contain only 0s for the first subarray, only 1s for the second subarray, etc. So, df['index3'] = subarray_number, where subarray_number goes from 0 to a-1. Only the column at index3 is changed.
So, the fifth subarray represented as a dataframe would look like this:
index0 | index1 | index2 | index3 | index4 | index5 | value
------------------------------------------------------------
0 | 0 | 0 | 4 | 0 | 0 | 434.2
0 | 0 | 0 | 4 | 0 | 1 | 234.5
...
x-1 | y-1 | z-1 | 4 | b-1 | c-1 | 371.8
After this, I only have to iterate over the rows of each of the dataframes using iterrows, and assign the values to the corresponding indices of the array of zeros, like this:
for subarray_df in subarrays_dfs:
for i, row in subarray_df.iterrows():
index0, index1, index2, index3, index4, index5, value = row
L[index0][index1][index2][index3][index4][index5] = value
The problem is that converting the arrays to dataframes and then assigning the values one by one is expensive, especially for large arrays. I would like to insert the subarrays in L directly without having to go through this intermediate step.
I tried using slices but the generated array is not the one I expect. This is what I'm doing:
L[:subarray.shape[0], :subarray.shape[1], :subarray.shape[2],
subarray_number, :subarray.shape[4], :subarray.shape[5]] = subarray
What would be the right way of using slices to fill L the way I need?
Thanks!