Isaac
Isaac

Reputation: 390

Indexing failure/odd behaviour with array

I have some code that is intended to convert a 3-dimensional list to an array. Technically it works in that I get a 3-dimensional array, but indexing only works when I don't iterate accross one of the dimensions, and doesn't work if I do.

Indexing works here:

listTempAllDays = []
for j in listGPSDays:
    listTempDay = []
    for i in listGPSDays[0]:
        arrayDay = np.array(i)
        listTempDay.append(arrayDay)
    arrayTemp = np.array(listTempDay)
    listTempAllDays.append(arrayTemp)

arrayGPSDays = np.array(listTempAllDays)
print(arrayGPSDays[0,0,0])

It doesn't work here:

listTempAllDays = []
for j in listGPSDays:
    listTempDay = []
    for i in j:
        arrayDay = np.array(i)
        listTempDay.append(arrayDay)
    arrayTemp = np.array(listTempDay)
    listTempAllDays.append(arrayTemp)

arrayGPSDays = np.array(listTempAllDays)
print(arrayGPSDays[0,0,0])

The difference between the two pieces of code is in the inner for loop. The first piece of code also works for all elements in listGPSDays (e.g. for i in listGPSDays[1]: etc...).

Removing the final print call allows the code to run in the second case, or changing the final line to print(arrayGPSDays[0][0,0]) does also run.

In both cases checking the type at all levels returns <class 'numpy.ndarray'>.

I would like this array indexing to work, if possible - what am I missing?

The following is provided as example data:

Anonymised results from print(arrayGPSDays[0:2,0:2,0:2]), generated using the first piece of code (so that the indexing works! - but also resulting in arrayGPSDays[0] being the same as arrayGPSDays[1]):

    [[['1' '2']
      ['3' '4']]

     [['1' '2']
      ['3' '4']]]

Upvotes: 0

Views: 71

Answers (2)

Matt Messersmith
Matt Messersmith

Reputation: 13747

numpy's array constructor can handle arbitrarily dimensioned iterables. They only stipulation is that they can't be jagged (i.e. each "row" in each dimension must have the same length).

Here's an example:

In [1]: list_3d = [[['a', 'b', 'c'], ['d', 'e', 'f']], [['g', 'h',  'i'], ['j', 'k', 'l']]]

In [2]: import numpy as np

In [3]: np.array(list_3d)
Out[3]: 
array([[['a', 'b', 'c'],
        ['d', 'e', 'f']],

       [['g', 'h', 'i'],
        ['j', 'k', 'l']]], dtype='<U1')

In [4]: array_3d = np.array(list_3d)

In [5]: array_3d[0,0,0]
Out[5]: 'a'

In [6]: array_3d.shape
Out[6]: (2, 2, 3)

If the array is jagged, numpy will "squash" down to the dimension where the jagged-ness happens. Since that explanation is clear as mud, an example might help:

In [20]: jagged_3d = [ [['a', 'b'], ['c', 'd']], [['e', 'f'], ['g', 'h'], ['i', 'j']] ]

In [21]: jagged_arr = np.array(jagged_3d)

In [22]: jagged_arr.shape
Out[22]: (2,)

In [23]: jagged_arr
Out[23]: 
array([list([['a', 'b'], ['c', 'd']]),
       list([['e', 'f'], ['g', 'h'], ['i', 'j']])], dtype=object)

The reason the constructor isn't working out of the box is because you have a jagged array. numpy simply does not support jagged arrays due to the fact that each numpy array has a well-defined shape representing the length of each dimension. So if the items in a given dimension are different lengths, this abstraction falls apart, and numpy simply doesn't allow it.

HTH.

Upvotes: 1

Fabricio Montagnani
Fabricio Montagnani

Reputation: 46

So Isaac, it seems your code have some syntax misinterpretations,

In your for statement, j represents an ITEM inside the list listGPSDays (I assume it is a list), not the ITEM INDEX inside the list, and you don't need to "get" the range of the list, python can do it for yourself, try:

for j in listGPSdays:

instead of

for j in range(len(listGPSDays)):

Also, try changing this line of code from:

for i in listGPSDays[j]:

to:

for i in listGPSDays.index(j):

I think it will solve your problem, hope it works!

Upvotes: 0

Related Questions