0

How do I get accumulate working with use-defined ufuncs?

import numpy as np

def leak(x, jump):
   return x * 0.9 + jump
 
leaku = np.frompyfunc(leak, 2, 1)
leaku.accumulate(np.array([0, 1, 1, 0, 0, 0.0]))  # ideally [0, 1.0, 1.9, 1.9*0.9, etc.]

produces

ValueError: could not find a matching type for leak (vectorized).accumulate, requested type has type code 'd'
Neil G
  • 32,138
  • 39
  • 156
  • 257

2 Answers2

4

numpy.frompyfunc can only produce ufuncs with object dtype output, but ufunc.accumulate defaults to using the input dtype as the dtype for intermediate results. (That, or the dtype of the out array if you provide one, but you didn't provide one.) When you pass in an array of float64 dtype, ufunc.accumulate looks for a ufunc loop with float64 output, and it doesn't find one.

You can pass in an array of object dtype, like np.array([0, 1, 1, 0, 0, 0.0], dtype=np.object_), or you can override the default intermediate dtype with leaku.accumulate(np.array([0, 1, 1, 0, 0, 0.0]), dtype=np.object_).

Note that numpy.frompyfunc ufuncs are as slow as any other Python-level code, not "NumPy speed", and object arrays have much worse speed and memory characteristics than normal arrays, as well as other inconvenient behavior. I wouldn't recommend using numpy.frompyfunc. Consider using Numba instead.

Neil G
  • 32,138
  • 39
  • 156
  • 257
user2357112
  • 260,549
  • 28
  • 431
  • 505
1

Try this:

result = leaku.accumulate(np.array([0, 1, 1, 0, 0, 0.0]), dtype=np.object).astype(np.float)
print(result)

Output

[0.     1.     1.9    1.71   1.539  1.3851]
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76