2

I am using trying to convert the following to a 2x2 numpy array of interval objects:

from interval import interval  # from the "pyinterval" package
import numpy as np

np.array([ 
    [interval([1.0, 2.0]), interval([1.0, 2.0])], 
    [interval([1.0, 2.0]), interval([1.0, 2.0])]
    ])

Unfortunately, this operation casts the intervals as numpy arrays, and gives me a 2x2x1x2 matrix. Is there any way I can prevent this from happening with numpy arrays or matrices?

I was able to get the desired result by populating an empty array first, where jac is a list of lists of intervals:

arr = np.empty(shape=(2,2), dtype=interval)

for i in range(len(arr)):
    for j in range(len(arr)):
        arr[i][j] = jac[i][j]

That being said, I suspect there's a more elegant way to achieve this. Is there a more "pythonic" way to do this?

4
  • 1
    What is interval? You can't call a module as if it were a function just like that. Commented May 1, 2017 at 15:54
  • Hi! Sorry about that, I was using pyinterval; I've corrected by question. Thanks! Commented May 1, 2017 at 16:07
  • Interval objects apparently look like lists. Commented May 1, 2017 at 16:10
  • Yes you have to use the allocate and fill. Sometimes the fill can be done as a whole or by slices. Commented May 1, 2017 at 16:19

3 Answers 3

2

It seems like numpy will coerce anything Sequence-like into a new dimension, even if np.array is called with dtype=object. You can work around this by directly making an empty array with dtype=object and then filling it manually.

interval_list = get_intervals()
interval_array = np.ndarray(len(interval_list), dtype=object)

for i, interv in enumerate(interval_list):
   interval_array[i] = interv
Sign up to request clarification or add additional context in comments.

Comments

0

You don't need the explicit loop when populating the empty array, you can just assign with [:]:

class interval(list):
    """I don't have any real interval but this should work."""
    def __repr__(self):
        return 'interval({})'.format(super().__repr__())

import numpy as np

>>> a = np.empty((2, 2), dtype=object)

>>> a[:] = [[interval([1.0, 2.0]), interval([1.0, 2.0])], 
...         [interval([1.0, 2.0]), interval([1.0, 2.0])]]

>>> a
array([[interval([1.0, 2.0]), interval([1.0, 2.0])],
       [interval([1.0, 2.0]), interval([1.0, 2.0])]], dtype=object)
>>> a.shape
(2, 2)
>>> a[0, 0]
interval([1.0, 2.0])

Unfortunatly there is no way to explicitly tell numpy.array which classes shouldn't be unpacked so you probably need to create the empty array first.


On a side note: There is not "interval" dtype for numpy arrays, if it's an unrecognized dtype it will use object. Using dtype=interval may be confusing for other readers because they might expect an efficient dtype.

Comments

0

With the assign and fill approach it is often possible to assign multiple items from a list. I have a vague memory that sometimes that doesn't work, but it does work for lists:

In [84]: jac = [[[1,2],[1,2]],[[1,2],[1,2]]]
In [85]: arr = np.empty((2,2),dtype=object)
In [86]: arr[...] = jac
In [87]: arr
Out[87]: 
array([[[1, 2], [1, 2]],
       [[1, 2], [1, 2]]], dtype=object)
In [88]: arr[1,0]
Out[88]: [1, 2]

p.s. it also works for jac = [[[[1,2]],[[1,2]]],[[[1,2]],[[1,2]]]], which would produce a (2,2,1,2) is used as np.array(jac).

1 Comment

"I have a vague memory that sometimes that doesn't work", only if some implicit broadcasting or unpacking is involved. I've never encountered a problem when the shapes were identical.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.