# Python Vectorizing a Function Returning an Array

I have the following function that has been vectorized so that for every element in input array t, an array is output:

@np.vectorize
def Ham(t):
d=np.array([[np.cos(t),np.sqrt(t)],[0,1]],dtype=np.complex128)
return d


I am getting an error: TypeError: only length-1 arrays can be converted to Python scalars. I believe this error happens when there is conflicts with numpy and python, but I can't see where that would be. Also, if the dtype is not given, the error is ValueError: setting an array element with a sequence. I'm guessing you can't assign arrays inside arrays in python, but how else can I do this?

The problem is that np.cos(t) and np.sqrt(t) generate arrays with the length of t, whereas the second row ([0,1]) maintains the same size. To use np.vectorize with your function, you have to define the output type, and np.vectorize isn't really meant as a decorator except for the simplest cases. In this way however you can generate the function with the right type:

def Ham(t):
d=np.array([[np.cos(t),np.sqrt(t)],[0,1]],dtype=np.complex128)
return d

HamVec = np.vectorize(Ham, otypes=[np.ndarray])


Now you can use HamVec as a function:

>>> x=np.array([1,2,3])
>>> HamVec(x)
array([ array([[ 0.54030231+0.j,  1.00000000+0.j],
[ 0.00000000+0.j,  1.00000000+0.j]]),
array([[-0.41614684+0.j,  1.41421356+0.j],
[ 0.00000000+0.j,  1.00000000+0.j]]),
array([[-0.98999250+0.j,  1.73205081+0.j],
[ 0.00000000+0.j,  1.00000000+0.j]])], dtype=object)


Notes:

1. The np.vectorize is just a convenience function, it doesn't actually make code run any faster.
2. This question might have been more suitable for StackOverflow.

Edit: as an answer to the follow up question: the resulting values of the matrix are of type numpy.complex128:

>>> y = HamVec(x)
>>> type(y[0][0][0])
<type 'numpy.complex128'>


And you can do for example:

>>> y*np.complex('3+2j')
array([ array([[ 1.62090692+1.08060461j,  3.00000000+2.j        ],
[ 0.00000000+0.j        ,  3.00000000+2.j        ]]),
array([[-1.24844051-0.83229367j,  4.24264069+2.82842712j],
[ 0.00000000+0.j        ,  3.00000000+2.j        ]]),
array([[-2.96997749-1.97998499j,  5.19615242+3.46410162j],
[ 0.00000000+0.j        ,  3.00000000+2.j        ]])], dtype=object)

• That worked, thanks! I just have another question though. Is there a way to change the output to be of type cfloat? I tried converting it inside the function, but it always returns an array of dtype=object
– Alex
Jan 11 '16 at 17:14
• Are you sure this matters? The values in the result matrix are in fact of type numpy.complex128. Also see this question. Jan 11 '16 at 17:35
• Hmm I thought the dtype=object meant that the result matrix was of object type. Is there a reason why it says that it is of type object and not complex128?
– Alex
Jan 11 '16 at 19:10
• I have added an example to the answer. Jan 11 '16 at 19:17
• Okay sorry if I keep asking questions here, but I am trying to take numpy.linalg.eig of the resulting matrix, but since there is dtype=object in the matrix, I get an error. Is there a simple way of removing dtype in the output array?
– Alex
Jan 12 '16 at 1:35