Note
Click here to download the full example code
Numpy tutorial
This tutorial shows how pynapple interact with numpy.
Multiple time series object are avaible depending on the shape of the data.
TsdTensor
: for data with of more than 2 dimensions, typically movies.TsdFrame
: for column-based data. It can be easily converted to a pandas.DataFrame. Columns can be labelled and selected similar to pandas.Tsd
: One-dimensional time series. It can be converted to a pandas.Series.Ts
: For timestamps data only.
Initialization
tsdtensor = nap.TsdTensor(t=np.arange(100), d=np.random.rand(100, 5, 5), time_units="s")
tsdframe = nap.TsdFrame(t=np.arange(100), d=np.random.rand(100, 3), columns = ['a', 'b', 'c'])
tsd = nap.Tsd(t=np.arange(100), d=np.random.rand(100))
ts = nap.Ts(t=np.arange(100))
print(tsdtensor)
Out:
Time (s)
---------- -----------------------------
0.0 [[0.51727 ... 0.895404] ...]
1.0 [[0.663393 ... 0.475589] ...]
2.0 [[0.715128 ... 0.152147] ...]
3.0 [[0.97744 ... 0.191655] ...]
...
96.0 [[0.782558 ... 0.747341] ...]
97.0 [[0.943785 ... 0.172032] ...]
98.0 [[0.715992 ... 0.602271] ...]
99.0 [[0.135815 ... 0.552682] ...]
dtype: float64, shape: (100, 5, 5)
tsd and ts can be converted to a pandas.Series
Out:
0.0 0.667768
1.0 0.961549
2.0 0.284037
3.0 0.861665
4.0 0.706899
...
95.0 0.372483
96.0 0.462183
97.0 0.821270
98.0 0.796485
99.0 0.276541
Length: 100, dtype: float64
tsdframe to a pandas.DataFrame
Out:
a b c
0.0 0.491233 0.821658 0.231000
1.0 0.021707 0.605881 0.247355
2.0 0.517196 0.360838 0.935419
3.0 0.840220 0.581280 0.320756
4.0 0.086720 0.292620 0.250157
... ... ... ...
95.0 0.488267 0.673744 0.340825
96.0 0.859655 0.815793 0.270190
97.0 0.425349 0.459970 0.170645
98.0 0.666319 0.694995 0.359913
99.0 0.506265 0.712584 0.027225
[100 rows x 3 columns]
Attributes
The numpy array is accesible with the attributes .values
, .d
and functions .as_array()
, to_numpy()
.
The time index array is a TsIndex
object accessible with .index
or .t
.
.shape
and .ndim
are also accessible.
Out:
Slicing
Slicing is very similar to numpy array. The first dimension is always time and time support is always passed on if a pynapple object is returned.
First 10 elements. Return a TsdTensor
Out:
Time (s)
---------- -----------------------------
0.0 [[0.51727 ... 0.895404] ...]
1.0 [[0.663393 ... 0.475589] ...]
2.0 [[0.715128 ... 0.152147] ...]
3.0 [[0.97744 ... 0.191655] ...]
...
6.0 [[0.359447 ... 0.96622 ] ...]
7.0 [[0.195038 ... 0.334129] ...]
8.0 [[0.081557 ... 0.87235 ] ...]
9.0 [[0.688747 ... 0.82844 ] ...]
dtype: float64, shape: (10, 5, 5)
First column. Return a Tsd
Out:
Time (s)
---------- --------
0.0 0.491233
1.0 0.021707
2.0 0.517196
3.0 0.84022
...
96.0 0.859655
97.0 0.425349
98.0 0.666319
99.0 0.506265
dtype: float64, shape: (100,)
First element. Return a numpy ndarray
Out:
[[0.51727018 0.03390075 0.80112565 0.220407 0.89540419]
[0.34067737 0.44790932 0.17439861 0.74983707 0.96356808]
[0.20851396 0.24139841 0.15517256 0.12697945 0.39269327]
[0.70361303 0.63303247 0.18126372 0.31986829 0.79197851]
[0.46459993 0.50450667 0.56674669 0.4214567 0.61710529]]
The time support is never changing when slicing time down.
Out:
TsdFrame offers special slicing similar to pandas.DataFrame.
Only TsdFrame can have columns labelling and indexing.
Out:
Time (s)
---------- --------
0.0 0.491233
1.0 0.021707
2.0 0.517196
3.0 0.84022
...
96.0 0.859655
97.0 0.425349
98.0 0.666319
99.0 0.506265
dtype: float64, shape: (100,)
Time (s) a c
---------- ------- -------
0.0 0.49123 0.231
1.0 0.02171 0.24736
2.0 0.5172 0.93542
3.0 0.84022 0.32076
...
96.0 0.85965 0.27019
97.0 0.42535 0.17065
98.0 0.66632 0.35991
99.0 0.50626 0.02723
dtype: float64, shape: (100, 2)
Arithmetic
Arithmetical operations works similar to numpy
Out:
It is possible to do array operations on the time series provided that the dimensions matches. The output will still be a time series object.
Out:
Nevertheless operations like this are not permitted :
Out:
operand type(s) all returned NotImplemented from __array_ufunc__(<ufunc 'add'>, '__call__', Time (s)
---------- --
0 1
1 1
2 1
3 1
4 1
dtype: float64, shape: (5,), Time (s)
---------- --
0 1
1 1
2 1
3 1
4 1
dtype: float64, shape: (5,)): 'Tsd', 'Tsd'
Array operations
The most common numpy functions will return a time series if the output first dimension matches the shape of the time index.
Here i average along the time axis and get a numpy array.
Out:
[[0.52589452 0.50174754 0.50506025 0.48152077 0.51595008]
[0.55095398 0.46214611 0.54968335 0.51852571 0.52859276]
[0.47158591 0.47607442 0.440397 0.55331884 0.48584168]
[0.53460863 0.48979848 0.50509807 0.50842717 0.52187273]
[0.47743813 0.53697914 0.52845496 0.47686796 0.47048325]]
Here I average across the second dimension and get a TsdFrame
Out:
Time (s) 0 1 2 3 4
---------- ------- ------- ------- ------- -------
0.0 0.44693 0.37215 0.37574 0.36771 0.73215
1.0 0.33879 0.72026 0.55459 0.33577 0.56504
2.0 0.6017 0.50521 0.63258 0.6617 0.33103
3.0 0.59543 0.59335 0.59358 0.4719 0.37095
...
96.0 0.5188 0.59509 0.42638 0.49497 0.56845
97.0 0.49106 0.41528 0.43646 0.54842 0.37963
98.0 0.57957 0.46595 0.55713 0.6007 0.37686
99.0 0.3893 0.74429 0.44128 0.36305 0.48983
dtype: float64, shape: (100, 5)
This is not true for fft functions though.
Out:
no implementation found for 'numpy.fft.fft' on types that implement __array_function__: [<class 'pynapple.core.time_series.Tsd'>]
Concatenating
It is possible to concatenate time series providing than they don't overlap meaning time indexe should be already sorted through all time series to concatenate
tsd1 = nap.Tsd(t=np.arange(5), d=np.ones(5))
tsd2 = nap.Tsd(t=np.arange(5)+10, d=np.ones(5)*2)
tsd3 = nap.Tsd(t=np.arange(5)+20, d=np.ones(5)*3)
print(np.concatenate((tsd1, tsd2, tsd3)))
Out:
Time (s)
---------- --
0.0 1
1.0 1
2.0 1
3.0 1
...
21.0 3
22.0 3
23.0 3
24.0 3
dtype: float64, shape: (15,)
It's also possible to concatenate vertically if time indexes matches up to pynapple float precision
tsdframe = nap.TsdFrame(t=np.arange(5), d=np.random.randn(5, 3))
print(np.concatenate((tsdframe, tsdframe), 1))
Out:
Time (s) 0 1 2 3 4 ...
---------- -------- -------- -------- -------- -------- -----
0 -1.41809 -0.58444 -0.03468 -1.41809 -0.58444 ...
1 0.42963 0.12006 0.13157 0.42963 0.12006 ...
2 1.70302 1.76859 0.41192 1.70302 1.76859 ...
3 0.57145 0.9053 -0.68933 0.57145 0.9053 ...
4 1.91562 -2.25739 -0.19457 1.91562 -2.25739 ...
dtype: float64, shape: (5, 6)
Spliting
Array split functions are also implemented
Out:
[Time (s)
---------- -----------------------------
0 [[0.51727 ... 0.895404] ...]
1 [[0.663393 ... 0.475589] ...]
2 [[0.715128 ... 0.152147] ...]
3 [[0.97744 ... 0.191655] ...]
4 [[0.035912 ... 0.160205] ...]
dtype: float64, shape: (5, 5, 5), Time (s)
---------- -----------------------------
5 [[0.629097 ... 0.860984] ...]
6 [[0.359447 ... 0.96622 ] ...]
7 [[0.195038 ... 0.334129] ...]
8 [[0.081557 ... 0.87235 ] ...]
9 [[0.688747 ... 0.82844 ] ...]
dtype: float64, shape: (5, 5, 5)]
Modifying
It is possible to modify a time series element wise
Out:
Time (s)
---------- --
0 1
1 1
2 1
3 1
4 1
dtype: float64, shape: (5,)
Time (s)
---------- -------
0 3.14159
1 1
2 1
3 1
4 1
dtype: float64, shape: (5,)
It is also possible to modify a time series with logical operations
Out:
Sorting
It is not possible to sort along the first dimension as it would break the sorting of the time index
tsd = nap.Tsd(t=np.arange(100), d=np.random.rand(100))
try:
np.sort(tsd)
except Exception as error:
print(error)
Out:
no implementation found for 'numpy.sort' on types that implement __array_function__: [<class 'pynapple.core.time_series.Tsd'>]
Total running time of the script: ( 0 minutes 0.810 seconds)
Download Python source code: tutorial_pynapple_numpy.py