0

I have a function which takes a numpy array and outputs a numpy array. However, when the output array contains a constant value, calling the function with a numpy array results in said value being "collapsed".

I'm trying to write a vector calculus library using numpy, and would like to pass vectors to vector valued functions instead of relying on iteration.

r1 = lambda t: np.array([2*t, 1])
r2 = lambda t: np.array([2*t, 1+0*t])
t = np.linspace(0, 1)
print(r1(t).shape)
print(r2(t).shape)

One would expect r1(t) and r2(t) to have the same shape, however this is not the case. r1(t) results in an object that looks something like array([ array([...]), 1, dtype=object), and r2(t) results in something that looks like array([ [...], [...]) (where [...] denotes a valid array of floats). I'm guessing that r2(t) works properly because of varying floating point errors, but I could be wrong. Is there a way to prevent numpy from collapsing the second row, or "expand" it?

1 Answers1

1
In [183]: r1 = lambda t: np.array([2*t, 1]) 
     ...: r2 = lambda t: np.array([2*t, 1+0*t]) 
     ...: t = np.linspace(0, 1)                                                                              
In [184]: r1(t)                                                                                              
Out[184]: 
array([array([0.        , 0.04081633, 0.08163265, 0.12244898, 0.16326531,
       0.20408163, 0.24489796, 0.28571429, 0.32653061, 0.36734694,
       0.40816327, 0.44897959, 0.48979592, 0.53061224, 0.57142857,
       0.6122449 , 0.65306122, 0.69387755, 0.73469388, 0.7755102 ,
       0.81632653, 0.85714286, 0.89795918, 0.93877551, 0.97959184,
       1.02040816, 1.06122449, 1.10204082, 1.14285714, 1.18367347,
       1.2244898 , 1.26530612, 1.30612245, 1.34693878, 1.3877551 ,
       1.42857143, 1.46938776, 1.51020408, 1.55102041, 1.59183673,
       1.63265306, 1.67346939, 1.71428571, 1.75510204, 1.79591837,
       1.83673469, 1.87755102, 1.91836735, 1.95918367, 2.        ]),
       1], dtype=object)
In [185]: r2(t)                                                                                              
Out[185]: 
array([[0.        , 0.04081633, 0.08163265, 0.12244898, 0.16326531,
        0.20408163, 0.24489796, 0.28571429, 0.32653061, 0.36734694,
        0.40816327, 0.44897959, 0.48979592, 0.53061224, 0.57142857,
        0.6122449 , 0.65306122, 0.69387755, 0.73469388, 0.7755102 ,
        0.81632653, 0.85714286, 0.89795918, 0.93877551, 0.97959184,
        1.02040816, 1.06122449, 1.10204082, 1.14285714, 1.18367347,
        1.2244898 , 1.26530612, 1.30612245, 1.34693878, 1.3877551 ,
        1.42857143, 1.46938776, 1.51020408, 1.55102041, 1.59183673,
        1.63265306, 1.67346939, 1.71428571, 1.75510204, 1.79591837,
        1.83673469, 1.87755102, 1.91836735, 1.95918367, 2.        ],
       [1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ,
        1.        , 1.        , 1.        , 1.        , 1.        ]])
In [186]: r1(t).shape                                                                                        
Out[186]: (2,)
In [187]: r2(t).shape                                                                                        
Out[187]: (2, 50)

r2 combines two arrays that match t in shape (50,), so the result is a (2,50) shaped numeric array.

r1 combines a (50,) array with a scalar 1. The result is a 2 element array, object dtype. See that dangling 1 at the end of the r1 display? Mixing elements of different size produces a list like array, because it can't make the multidimensional array as with r2

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • I see, is there a simple way to expand the dangling 1 at the end of r1, so it would play nicely with other numpy routines, or should I change my approach to defining vector valued functions as np.array wrapped in a lambda? – accountable accountant account Aug 27 '19 at 01:47
  • `r2` is a reasonable approach. `np.ones_like(t)` is another. – hpaulj Aug 27 '19 at 03:32