I have some time data which starts at T0 and goes to T1 in steps of dt. This data is in small increments of dt and is currently stored as a numpy array and as such uses a lot of space. A more efficient way to store this would be to store T0, T1 and dt, e.g. using a generator. However generators don't work with many functions, e.g. numpy functions, arithmetic and plotting. I want something which works like a generator, i.e. only stores the 3 necessary values, and then generates a numpy array when necessary to use for use in some function or so.
Is there any object that already exists that works like this? I.e. Storing the necessary data (3 values) in a generator and then returning/representing itself as a numpy array when used in functions or arithmetic? The memory would only then be used while within the scope of the function and be released when it falls out of scope.
EDIT with solution: I created an mplementation what I wanted. Copying generators turned out to be tricky, see here, so I instead store the start, stop and step and create and return generators or numpy arrays as required.
The code for this is as follows:
import numpy as _np
class frange():
"""
Return an object can be used to generate a generator or an array
of floats from start (inclusive) to stop (exclusive) by step.
This object stores the start, stop, step and length of
the data. Uses less memory than storing a large array.
Example
-------
An example of how to use this class to generate some data is
as follows for some time data between 0 and 2 in steps of
1e-3 (0.001)::
$ time = frange(0, 2, 1e-3)
$ printlen(time) # prints length of frange, just like an array or list
$ generator = time.get_generator() # gets a generator instance
$ for i in generator: # iterates through printing each element
$ print(i)
$ array = time.get_array() # gets an array instance
$ newarray = 5 * array # multiplies array by 5
"""
def __init__(self, start, stop, step):
"""
Intialises frange class instance. Sets start, top, step and
len properties.
Parameters
----------
start : float
starting point
stop : float
stopping point
step : float
stepping interval
"""
self._slice = slice(start, stop, step)
self.len = self.get_array().size
return None
def get_generator(self):
"""
Returns a generator for the frange object instance.
Returns
-------
gen : generator
A generator that yields successive samples from start (inclusive)
to stop (exclusive) in step steps.
"""
s = self._slice
gen = drange(s.start, s.stop, s.step) # intialises the generator
return gen
def get_array(self):
"""
Returns an numpy array containing the values from start (inclusive)
to stop (exclusive) in step steps.
Returns
-------
array : ndarray
Array of values from start (inclusive)
to stop (exclusive) in step steps.
"""
s = self._slice
array = _np.arange(s.start, s.stop, s.step)
return array
def __len__(self):
return self.len
def drange(start, stop, step):
"""
A generator that yields successive samples from start (inclusive)
to stop (exclusive) in step intervals.
Parameters
----------
start : float
starting point
stop : float
stopping point
step : float
stepping interval
Yields
------
x : float
next sample
"""
x = start
if step > 0:
while x + step <= stop: # produces same behaviour as numpy.arange
yield x
x += step
elif step < 0:
while x + step >= stop: # produces same behaviour as numpy.arange
yield x
x += step
else:
raise ZeroDivisionError("Step must be non-zero")