Creating and bundling custom profilers¶
[1]:
from typing import Union, Tuple, Optional
import itertools as it
import numpy as np
import pandas as pd
import statsmodels.tsa.api as sm
Profiling Functions¶
Creating a customer profiler is very straightforward. For a function to qualify as a profiler it needs:
To be type annotated
To have one and only one positional argument, the timeseries, which needs to be a pandas DataFrame or Series (or a union of both)
To be decorated with
@ProfilingFunction
Let’s use a few dummy examples to better illustrate this.
[3]:
from tslumen.profile import ProfilingFunction
[4]:
@ProfilingFunction
def shape(data: Union[pd.Series, pd.DataFrame]) -> Tuple[int, ...]:
return data.shape
shape
[4]:
As shown by the checkmarks, the shape
function we just created is applied to the DataFrame as a whole, as well as each individual series.
Under the hood, the @ProfilingFunction
decorator inspects the function and wraps it inside a class which, among other purposes, identifies the scope of action of the profiler (i.e. single Series, DataFrame or both), particularly useful when orchestrating the execution of multiple profilers. More on that later.
[5]:
@ProfilingFunction
def acovf(data: pd.Series, adjusted: bool = False, demean: bool = True,
fft: bool = True, missing: str = 'none', nlag: Optional[int] = None) -> pd.Series:
est = sm.acovf(data.values, adjusted=adjusted, demean=demean, fft=fft, missing=missing, nlag=nlag)
return pd.Series(est, index=data.index)
acovf
[5]:
[6]:
@ProfilingFunction
def euc_sim(data: pd.DataFrame, measure: str = 'rmse') -> pd.DataFrame:
fn = lambda d: d.mean() if measure == 'mean' else np.sqrt((d**2).mean())
res = {(a, b): fn(data[b]-data[a])
for a, b in it.product(data.columns, data.columns)}
return pd.Series(res).unstack(0)
euc_sim
[6]:
Now the acovf
function is for Series only, whereas euc_sim
is for DataFrames only.
When wrapping functionality from another library, it is a good idea to expose (some of) its parameters as to make the profiler more configurable. Naturally, in some cases, it’s actually a good idea to hide them from the end-user, particularly when the wrapper itself will have the logic to select the parameters.
Note that any arguments the profiling function exposes (other than the first one) need to have defaults.
Let’s load a dataset and try out these profilers
[7]:
df = pd.read_csv('https://datahub.io/core/s-and-p-500/r/data.csv', parse_dates=[0], index_col=0)
df = df[(df.index >= '1990-01-01') & (df.index < '2015-01-01')]
df.head()
[7]:
SP500 | Dividend | Earnings | Consumer Price Index | Long Interest Rate | Real Price | Real Dividend | Real Earnings | PE10 | |
---|---|---|---|---|---|---|---|---|---|
Date | |||||||||
1990-01-01 | 339.97 | 11.14 | 22.49 | 127.4 | 8.21 | 666.69 | 21.85 | 44.10 | 17.05 |
1990-02-01 | 330.45 | 11.23 | 22.08 | 128.0 | 8.47 | 644.99 | 21.92 | 43.10 | 16.51 |
1990-03-01 | 338.46 | 11.32 | 21.67 | 128.7 | 8.59 | 657.03 | 21.97 | 42.07 | 16.83 |
1990-04-01 | 338.18 | 11.44 | 21.53 | 128.9 | 8.79 | 655.46 | 22.17 | 41.74 | 16.81 |
1990-05-01 | 350.25 | 11.55 | 21.40 | 129.2 | 8.76 | 677.28 | 22.34 | 41.38 | 17.39 |
[8]:
shape(df)
[8]:
[9]:
shape(df.SP500)
[9]:
[10]:
acovf(df.SP500)
[10]:
Date | 1990-01-01 | 1990-02-01 | 1990-03-01 | 1990-04-01 | 1990-05-01 | 1990-06-01 | 1990-07-01 | 1990-08-01 | 1990-09-01 | 1990-10-01 | ... | 2014-03-01 | 2014-04-01 | 2014-05-01 | 2014-06-01 | 2014-07-01 | 2014-08-01 | 2014-09-01 | 2014-10-01 | 2014-11-01 | 2014-12-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 179217.457496 | 175888.867311 | 172240.056519 | 168900.130792 | 165215.340345 | 161487.048775 | 157530.850357 | 153705.459385 | 149985.479096 | 146125.05111 | ... | -21330.750303 | -19308.50963 | -17303.253341 | -15288.805447 | -13242.503765 | -11143.461295 | -9034.245959 | -6815.498383 | -4723.390484 | -2356.619013 |
1 rows × 300 columns
[11]:
euc_sim(df, 'rmse')
[11]:
Consumer Price Index | Dividend | Earnings | Long Interest Rate | PE10 | Real Dividend | Real Earnings | Real Price | SP500 | |
---|---|---|---|---|---|---|---|---|---|
Consumer Price Index | 0.000000 | 165.486344 | 135.796101 | 181.364722 | 161.318178 | 159.546683 | 122.081817 | 1247.349170 | 935.855699 |
Dividend | 165.486344 | 0.000000 | 35.661179 | 17.019169 | 11.701936 | 6.940290 | 48.498664 | 1407.033108 | 1093.831545 |
Earnings | 135.796101 | 35.661179 | 0.000000 | 51.538956 | 34.956319 | 31.895157 | 15.897771 | 1375.411112 | 1060.978612 |
Long Interest Rate | 181.364722 | 17.019169 | 51.538956 | 0.000000 | 21.497434 | 22.065529 | 64.027759 | 1422.551992 | 1110.110884 |
PE10 | 161.318178 | 11.701936 | 34.956319 | 21.497434 | 0.000000 | 8.751860 | 45.141560 | 1401.371581 | 1089.657346 |
Real Dividend | 159.546683 | 6.940290 | 31.895157 | 22.065529 | 8.751860 | 0.000000 | 43.418904 | 1401.303869 | 1088.640134 |
Real Earnings | 122.081817 | 48.498664 | 15.897771 | 64.027759 | 45.141560 | 43.418904 | 0.000000 | 1361.394243 | 1048.086806 |
Real Price | 1247.349170 | 1407.033108 | 1375.411112 | 1422.551992 | 1401.371581 | 1401.303869 | 1361.394243 | 0.000000 | 364.090297 |
SP500 | 935.855699 | 1093.831545 | 1060.978612 | 1110.110884 | 1089.657346 | 1088.640134 | 1048.086806 | 364.090297 | 0.000000 |
All decorated functions return a ProfileResult
object, which is a mere wrapper around the function’s result to capture additional details like the name of the function, execution times, exceptions, etc.
It can be used as a class or cast as a dictionary.
[12]:
pr = shape(df.SP500)
dict(pr)
[12]:
{'name': 'shape',
'scope': 'series',
'target': 'SP500',
'start': datetime.datetime(2022, 11, 22, 17, 54, 44, 867712),
'end': datetime.datetime(2022, 11, 22, 17, 54, 44, 867761),
'success': True,
'warnings': [],
'exception': None,
'result': (300,)}
[13]:
pr.start
[13]:
datetime.datetime(2022, 11, 22, 17, 54, 44, 867712)
Bundling profilers together¶
Single profilers (i.e. ProfilingFunction
decorated functions) can be bundled together in one single class, which will deal with orchestrating their execution and collecting the results.
A DefaultProfiler
is included in tslumen, essentially bundling all the profiling functions included in the package.
Creating a custom bundle is simply a matter of creating a subclass of BundledProfiler
and defining the class variable _profilers
as a list of the profiling functions that are to be included. Note that these need to have unique names, as the name is used to store the output of the function.
Let’s start by having a look at the DefaultProfiler
.
[14]:
from tslumen.profile import DefaultProfiler
[15]:
DefaultProfiler.get_profilers()
[15]:
{'df_scaled': <tslumen.profile.base.ProfilingFunction at 0x7fcae9159a00>,
'dt_end': <tslumen.profile.base.ProfilingFunction at 0x7fcae914bc10>,
'dt_start': <tslumen.profile.base.ProfilingFunction at 0x7fcae914bcd0>,
'freq': <tslumen.profile.base.ProfilingFunction at 0x7fcae914b7f0>,
'infinite': <tslumen.profile.base.ProfilingFunction at 0x7fcae9159f10>,
'length': <tslumen.profile.base.ProfilingFunction at 0x7fcae9159d00>,
'missing': <tslumen.profile.base.ProfilingFunction at 0x7fcae9165f40>,
'n_series': <tslumen.profile.base.ProfilingFunction at 0x7fcae914b8b0>,
'period': <tslumen.profile.base.ProfilingFunction at 0x7fcae914b7c0>,
'sample': <tslumen.profile.base.ProfilingFunction at 0x7fcae9159760>,
'sz_total': <tslumen.profile.base.ProfilingFunction at 0x7fcae9159bb0>,
'zeros': <tslumen.profile.base.ProfilingFunction at 0x7fcae9159d90>,
'cov': <tslumen.profile.base.ProfilingFunction at 0x7fcae916ef10>,
'iqr': <tslumen.profile.base.ProfilingFunction at 0x7fcae9173640>,
'kurtosis': <tslumen.profile.base.ProfilingFunction at 0x7fcae91733d0>,
'mad': <tslumen.profile.base.ProfilingFunction at 0x7fcae916e130>,
'maximum': <tslumen.profile.base.ProfilingFunction at 0x7fcae9173460>,
'mean': <tslumen.profile.base.ProfilingFunction at 0x7fcae91652e0>,
'median': <tslumen.profile.base.ProfilingFunction at 0x7fcae91650d0>,
'minimum': <tslumen.profile.base.ProfilingFunction at 0x7fcae916ed60>,
'q25': <tslumen.profile.base.ProfilingFunction at 0x7fcae916ef40>,
'q50': <tslumen.profile.base.ProfilingFunction at 0x7fcae916e160>,
'q75': <tslumen.profile.base.ProfilingFunction at 0x7fcae916ee80>,
'skew': <tslumen.profile.base.ProfilingFunction at 0x7fcae9179a90>,
'std': <tslumen.profile.base.ProfilingFunction at 0x7fcae9165700>,
'var': <tslumen.profile.base.ProfilingFunction at 0x7fcae9165250>,
'adfuller_stationarity': <tslumen.profile.base.ProfilingFunction at 0x7fcae90546a0>,
'jarque_bera_normality': <tslumen.profile.base.ProfilingFunction at 0x7fcae9054580>,
'kpss_stationarity': <tslumen.profile.base.ProfilingFunction at 0x7fcae9061d90>,
'levene_constant_variance': <tslumen.profile.base.ProfilingFunction at 0x7fcae9179af0>,
'ljungbox_autocorrelation': <tslumen.profile.base.ProfilingFunction at 0x7fcae9179bb0>,
'omnibus_normality': <tslumen.profile.base.ProfilingFunction at 0x7fcae9054b50>,
'binned': <tslumen.profile.base.ProfilingFunction at 0x7fcae9002d60>,
'pd_percentiles': <tslumen.profile.base.ProfilingFunction at 0x7fcae9061700>,
'pd_quantiles': <tslumen.profile.base.ProfilingFunction at 0x7fcae900cf70>,
'acf': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94640>,
'acf_1d': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94d90>,
'acf_2d': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94130>,
'corr_kendall': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94520>,
'corr_pearson': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94cd0>,
'corr_spearman': <tslumen.profile.base.ProfilingFunction at 0x7fcae8da02e0>,
'granger_causality': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94ee0>,
'lag_corr': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94c40>,
'pacf': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94a90>,
'pacf_1d': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94160>,
'pacf_2d': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94f40>,
'seasonal_split': <tslumen.profile.base.ProfilingFunction at 0x7fcae8da0070>,
'stl': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d94760>,
'lowess': <tslumen.profile.base.ProfilingFunction at 0x7fcae8da0820>,
'rolling_avg': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db1670>,
'supsmu': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db5220>,
'ft_acf': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db20d0>,
'ft_adfuller': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db5550>,
'ft_cross_pts': <tslumen.profile.base.ProfilingFunction at 0x7fcae8d4e130>,
'ft_entropy': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db2070>,
'ft_kpss': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db52e0>,
'ft_pacf': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db5f40>,
'ft_stl': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db5430>,
'ft_tilewin': <tslumen.profile.base.ProfilingFunction at 0x7fcae8db5af0>}
The class method get_profilers
returns a dictionary with all the ProfilingFunction
bundled in this BundledProfiler
As the name suggests, the class method get_config_defaults
returns a dictionary with the default parameters of each ProfilingFunction
. It is useful for understanding exactly which parameter defaults can be overridden.
[16]:
DefaultProfiler.get_config_defaults()
[16]:
{'df_scaled': {},
'dt_end': {},
'dt_start': {},
'freq': {},
'infinite': {},
'length': {},
'missing': {},
'n_series': {},
'period': {},
'sample': {'sample_size': 10},
'sz_total': {'memory_deep': True},
'zeros': {},
'cov': {},
'iqr': {},
'kurtosis': {},
'mad': {},
'maximum': {},
'mean': {},
'median': {},
'minimum': {},
'q25': {},
'q50': {},
'q75': {},
'skew': {},
'std': {},
'var': {},
'adfuller_stationarity': {'confidence_level': 0.05},
'jarque_bera_normality': {'confidence_level': 0.05},
'kpss_stationarity': {'confidence_level': 0.05},
'levene_constant_variance': {'confidence_level': 0.05},
'ljungbox_autocorrelation': {'n_lags': None, 'confidence_level': 0.05},
'omnibus_normality': {'confidence_level': 0.05},
'binned': {'nbins': None},
'pd_percentiles': {},
'pd_quantiles': {},
'acf': {'lags': 40,
'adjusted': False,
'fft': False,
'alpha': 0.05,
'missing': 'none'},
'acf_1d': {'lags': 40,
'adjusted': False,
'fft': False,
'alpha': 0.05,
'missing': 'none'},
'acf_2d': {'lags': 40,
'adjusted': False,
'fft': False,
'alpha': 0.05,
'missing': 'none'},
'corr_kendall': {},
'corr_pearson': {},
'corr_spearman': {},
'granger_causality': {'test': 'ssr_chi2test',
'addconst': True,
'maxlag': 5,
'max_diff': 3,
'adf_confidence': 0.1},
'lag_corr': {'lags': ()},
'pacf': {'lags': 40, 'method': 'ywadjusted', 'alpha': 0.05},
'pacf_1d': {'lags': 40, 'method': 'ywadjusted', 'alpha': 0.05},
'pacf_2d': {'lags': 40, 'method': 'ywadjusted', 'alpha': 0.05},
'seasonal_split': {},
'stl': {'period': None,
'seasonal': 7,
'trend': None,
'low_pass': None,
'seasonal_deg': 0,
'trend_deg': 0,
'low_pass_deg': 0,
'robust': False,
'seasonal_jump': 1,
'trend_jump': 1,
'low_pass_jump': 1},
'lowess': {'fracs': (0.05, 0.1, 0.15),
'it': 3,
'delta': 0.0,
'missing': 'drop'},
'rolling_avg': {'wins': (), 'max_win_frac': 10},
'supsmu': {'alpha': None,
'period': None,
'primary_spans': (0.05, 0.2, 0.5),
'middle_span': 0.2,
'final_span': 0.05},
'ft_acf': {'n_diff': (0, 1, 2), 'n_size': (1, 10)},
'ft_adfuller': {},
'ft_cross_pts': {},
'ft_entropy': {'sampling_frequency': 1.0, 'n_per_segment': None},
'ft_kpss': {},
'ft_pacf': {'n_diff': (0, 1, 2), 'n_size': (5,)},
'ft_stl': {'freq': None},
'ft_tilewin': {}}
Let us now create our own profiler by bundling the functions defined above.
[17]:
from tslumen.profile import BundledProfiler
class MyProfiler(BundledProfiler):
_profilers = [shape, acovf, euc_sim]
[18]:
MyProfiler.get_profilers()
[18]:
{'shape': <tslumen.profile.base.ProfilingFunction at 0x7fcae639aa60>,
'acovf': <tslumen.profile.base.ProfilingFunction at 0x7fcae639ac10>,
'euc_sim': <tslumen.profile.base.ProfilingFunction at 0x7fcae639a940>}
[19]:
MyProfiler.get_config_defaults()
[19]:
{'shape': {},
'acovf': {'adjusted': False,
'demean': True,
'fft': True,
'missing': 'none',
'nlag': None},
'euc_sim': {'measure': 'rmse'}}
When instantiating the bundled profiler, the configs will be set, essentially by taking the defaults of each ProfilingFunction
and overriding any parameters explicitly provided as an argument.
[20]:
# default configs were set
profiler1 = MyProfiler()
profiler1.config
[20]:
{'shape': {},
'acovf': {'adjusted': False,
'demean': True,
'fft': True,
'missing': 'none',
'nlag': None},
'euc_sim': {'measure': 'rmse'}}
[21]:
# euc_sim's measure was overriden
profiler2 = MyProfiler(config={'euc_sim': {'measure': 'mean'}})
profiler2.config
[21]:
{'shape': {},
'acovf': {'adjusted': False,
'demean': True,
'fft': True,
'missing': 'none',
'nlag': None},
'euc_sim': {'measure': 'mean'}}
With our profiler instantiated, we can now profile our data. The bundled profiler will take care of orchestrating the execution of the profiling functions and collecting the results. Depending on the function’s scope, each will be called with the dataset or once per series.
[22]:
pr1 = profiler1.profile(df)
[23]:
pr2 = profiler2.profile(df)
[24]:
pr1
[24]:
exec_details
Profiler | Scope | Target | Start | End | Duration | Succeeded | Exceptions | # Runs | |
---|---|---|---|---|---|---|---|---|---|
0 | shape | frame | 2022-11-22 17:54:44.995921 | 2022-11-22 17:54:44.995990 | 0 days 00:00:00.000069 | True | None | 1 | |
1 | euc_sim | frame | 2022-11-22 17:54:44.998409 | 2022-11-22 17:54:45.020264 | 0 days 00:00:00.021855 | True | None | 1 | |
2 | shape | series | SP500 | 2022-11-22 17:54:45.021628 | 2022-11-22 17:54:45.021671 | 0 days 00:00:00.000043 | True | None | 1 |
3 | shape | series | Dividend | 2022-11-22 17:54:45.022741 | 2022-11-22 17:54:45.022775 | 0 days 00:00:00.000034 | True | None | 1 |
4 | shape | series | Earnings | 2022-11-22 17:54:45.023813 | 2022-11-22 17:54:45.023843 | 0 days 00:00:00.000030 | True | None | 1 |
5 | shape | series | Consumer Price Index | 2022-11-22 17:54:45.024853 | 2022-11-22 17:54:45.024883 | 0 days 00:00:00.000030 | True | None | 1 |
6 | shape | series | Long Interest Rate | 2022-11-22 17:54:45.025892 | 2022-11-22 17:54:45.025921 | 0 days 00:00:00.000029 | True | None | 1 |
7 | shape | series | Real Price | 2022-11-22 17:54:45.026930 | 2022-11-22 17:54:45.026960 | 0 days 00:00:00.000030 | True | None | 1 |
8 | shape | series | Real Dividend | 2022-11-22 17:54:45.027986 | 2022-11-22 17:54:45.028015 | 0 days 00:00:00.000029 | True | None | 1 |
9 | shape | series | Real Earnings | 2022-11-22 17:54:45.029048 | 2022-11-22 17:54:45.029078 | 0 days 00:00:00.000030 | True | None | 1 |
10 | shape | series | PE10 | 2022-11-22 17:54:45.030177 | 2022-11-22 17:54:45.030206 | 0 days 00:00:00.000029 | True | None | 1 |
11 | acovf | series | SP500 | 2022-11-22 17:54:45.031225 | 2022-11-22 17:54:45.031938 | 0 days 00:00:00.000713 | True | None | 1 |
12 | acovf | series | Dividend | 2022-11-22 17:54:45.032988 | 2022-11-22 17:54:45.033491 | 0 days 00:00:00.000503 | True | None | 1 |
13 | acovf | series | Earnings | 2022-11-22 17:54:45.034576 | 2022-11-22 17:54:45.035131 | 0 days 00:00:00.000555 | True | None | 1 |
14 | acovf | series | Consumer Price Index | 2022-11-22 17:54:45.036193 | 2022-11-22 17:54:45.036596 | 0 days 00:00:00.000403 | True | None | 1 |
15 | acovf | series | Long Interest Rate | 2022-11-22 17:54:45.037695 | 2022-11-22 17:54:45.038267 | 0 days 00:00:00.000572 | True | None | 1 |
16 | acovf | series | Real Price | 2022-11-22 17:54:45.039317 | 2022-11-22 17:54:45.039790 | 0 days 00:00:00.000473 | True | None | 1 |
17 | acovf | series | Real Dividend | 2022-11-22 17:54:45.040876 | 2022-11-22 17:54:45.041296 | 0 days 00:00:00.000420 | True | None | 1 |
18 | acovf | series | Real Earnings | 2022-11-22 17:54:45.042320 | 2022-11-22 17:54:45.042742 | 0 days 00:00:00.000422 | True | None | 1 |
19 | acovf | series | PE10 | 2022-11-22 17:54:45.043797 | 2022-11-22 17:54:45.044399 | 0 days 00:00:00.000602 | True | None | 1 |
config
- shape
-
acovf
- adjusted 0
- demean 1
- fft 1
- missing none
- nlag
-
euc_sim
- measure rmse
frame
-
shape
- 300
- 9
-
euc_sim
Consumer Price Index Dividend Earnings Long Interest Rate PE10 Real Dividend Real Earnings Real Price SP500 Consumer Price Index 0.000000 165.486344 135.796101 181.364722 161.318178 159.546683 122.081817 1247.349170 935.855699 Dividend 165.486344 0.000000 35.661179 17.019169 11.701936 6.940290 48.498664 1407.033108 1093.831545 Earnings 135.796101 35.661179 0.000000 51.538956 34.956319 31.895157 15.897771 1375.411112 1060.978612 Long Interest Rate 181.364722 17.019169 51.538956 0.000000 21.497434 22.065529 64.027759 1422.551992 1110.110884 PE10 161.318178 11.701936 34.956319 21.497434 0.000000 8.751860 45.141560 1401.371581 1089.657346 Real Dividend 159.546683 6.940290 31.895157 22.065529 8.751860 0.000000 43.418904 1401.303869 1088.640134 Real Earnings 122.081817 48.498664 15.897771 64.027759 45.141560 43.418904 0.000000 1361.394243 1048.086806 Real Price 1247.349170 1407.033108 1375.411112 1422.551992 1401.371581 1401.303869 1361.394243 0.000000 364.090297 SP500 935.855699 1093.831545 1060.978612 1110.110884 1089.657346 1088.640134 1048.086806 364.090297 0.000000
series
-
SP500
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 179217.457496 175888.867311 172240.056519 168900.130792 165215.340345 161487.048775 157530.850357 153705.459385 149985.479096 146125.05111 ... -21330.750303 -19308.50963 -17303.253341 -15288.805447 -13242.503765 -11143.461295 -9034.245959 -6815.498383 -4723.390484 -2356.619013 1 rows × 300 columns
-
-
Dividend
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 49.400977 48.606554 47.794709 46.966367 46.124609 45.273997 44.416014 43.551058 42.681026 41.808392 ... -4.913877 -4.491505 -4.052579 -3.600032 -3.134073 -2.653572 -2.15576 -1.640504 -1.108437 -0.561729 1 rows × 300 columns
-
-
Earnings
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 677.698755 669.673559 657.92764 643.170637 626.132013 607.439338 587.328768 566.06651 543.918129 521.181079 ... -49.219151 -44.510434 -39.753329 -34.898247 -29.945646 -24.880609 -19.760028 -14.58367 -9.542138 -4.681179 1 rows × 300 columns
-
-
Consumer Price Index
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 1046.925821 1037.008199 1026.620322 1015.986037 1005.218336 994.466492 983.714687 972.977294 962.481925 952.30536 ... -95.760634 -86.981831 -77.911929 -68.49001 -58.772746 -48.980822 -39.139278 -29.207523 -19.34701 -9.600817 1 rows × 300 columns
-
-
Long Interest Rate
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 3.206453 3.150692 3.079734 3.009203 2.937006 2.864374 2.802541 2.745641 2.686821 2.627148 ... -0.301043 -0.272852 -0.24273 -0.212285 -0.18481 -0.156489 -0.124337 -0.092837 -0.060652 -0.029786 1 rows × 300 columns
-
-
Real Price
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 185372.546946 182138.908686 178410.497863 175010.963782 171288.50299 167479.202707 163330.402897 159296.874 155213.734452 150767.462332 ... -16587.827481 -14952.145329 -13356.148569 -11798.267161 -10280.053473 -8718.552261 -7130.097809 -5417.025787 -3824.172983 -1908.431674 1 rows × 300 columns
-
-
Real Dividend
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 23.784269 23.307033 22.811945 22.305853 21.788526 21.257242 20.717799 20.169604 19.609093 19.035693 ... -1.788915 -1.635697 -1.476435 -1.319282 -1.16362 -1.000958 -0.828 -0.641519 -0.43859 -0.225194 1 rows × 300 columns
-
-
Real Earnings
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 627.922808 620.911342 608.835159 592.677006 573.408179 551.651944 527.755051 502.042683 474.838709 446.575623 ... -32.995829 -29.667612 -26.376891 -23.058698 -19.706581 -16.260724 -12.815635 -9.372833 -6.049005 -2.927201 1 rows × 300 columns
-
-
PE10
-
shape
- 300
-
acovf
Date 1990-01-01 1990-02-01 1990-03-01 1990-04-01 1990-05-01 1990-06-01 1990-07-01 1990-08-01 1990-09-01 1990-10-01 ... 2014-03-01 2014-04-01 2014-05-01 2014-06-01 2014-07-01 2014-08-01 2014-09-01 2014-10-01 2014-11-01 2014-12-01 0 46.669335 46.126725 45.410262 44.710637 43.980611 43.22205 42.378318 41.554839 40.681552 39.682067 ... -0.104916 -0.110232 -0.115056 -0.117495 -0.110682 -0.100873 -0.093304 -0.077496 -0.08024 -0.04124 1 rows × 300 columns
-
Results are held in a BundledResult
object, which includes the same details as ProfileResult
. Under the result
attribute you’ll find:
exec_details
a DataFrame with all the executionsconfig
the configurations passed onto this executionframe
a dictionary with the results of each profiling function whose scope is DataFrameseries
a dictionary with each of the series in the DataFrame, and for each series a dictionary with the results of the series profiling functions
[25]:
pr1.result.frame['euc_sim']
[25]:
Consumer Price Index | Dividend | Earnings | Long Interest Rate | PE10 | Real Dividend | Real Earnings | Real Price | SP500 | |
---|---|---|---|---|---|---|---|---|---|
Consumer Price Index | 0.000000 | 165.486344 | 135.796101 | 181.364722 | 161.318178 | 159.546683 | 122.081817 | 1247.349170 | 935.855699 |
Dividend | 165.486344 | 0.000000 | 35.661179 | 17.019169 | 11.701936 | 6.940290 | 48.498664 | 1407.033108 | 1093.831545 |
Earnings | 135.796101 | 35.661179 | 0.000000 | 51.538956 | 34.956319 | 31.895157 | 15.897771 | 1375.411112 | 1060.978612 |
Long Interest Rate | 181.364722 | 17.019169 | 51.538956 | 0.000000 | 21.497434 | 22.065529 | 64.027759 | 1422.551992 | 1110.110884 |
PE10 | 161.318178 | 11.701936 | 34.956319 | 21.497434 | 0.000000 | 8.751860 | 45.141560 | 1401.371581 | 1089.657346 |
Real Dividend | 159.546683 | 6.940290 | 31.895157 | 22.065529 | 8.751860 | 0.000000 | 43.418904 | 1401.303869 | 1088.640134 |
Real Earnings | 122.081817 | 48.498664 | 15.897771 | 64.027759 | 45.141560 | 43.418904 | 0.000000 | 1361.394243 | 1048.086806 |
Real Price | 1247.349170 | 1407.033108 | 1375.411112 | 1422.551992 | 1401.371581 | 1401.303869 | 1361.394243 | 0.000000 | 364.090297 |
SP500 | 935.855699 | 1093.831545 | 1060.978612 | 1110.110884 | 1089.657346 | 1088.640134 | 1048.086806 | 364.090297 | 0.000000 |
[26]:
pr2.result.frame['euc_sim']
[26]:
Consumer Price Index | Dividend | Earnings | Long Interest Rate | PE10 | Real Dividend | Real Earnings | Real Price | SP500 | |
---|---|---|---|---|---|---|---|---|---|
Consumer Price Index | 0.000000 | 163.441100 | 134.428367 | 178.143767 | 157.812267 | 156.987300 | 119.670567 | -1177.380400 | -847.525000 |
Dividend | -163.441100 | 0.000000 | -29.012733 | 14.702667 | -5.628833 | -6.453800 | -43.770533 | -1340.821500 | -1010.966100 |
Earnings | -134.428367 | 29.012733 | 0.000000 | 43.715400 | 23.383900 | 22.558933 | -14.757800 | -1311.808767 | -981.953367 |
Long Interest Rate | -178.143767 | -14.702667 | -43.715400 | 0.000000 | -20.331500 | -21.156467 | -58.473200 | -1355.524167 | -1025.668767 |
PE10 | -157.812267 | 5.628833 | -23.383900 | 20.331500 | 0.000000 | -0.824967 | -38.141700 | -1335.192667 | -1005.337267 |
Real Dividend | -156.987300 | 6.453800 | -22.558933 | 21.156467 | 0.824967 | 0.000000 | -37.316733 | -1334.367700 | -1004.512300 |
Real Earnings | -119.670567 | 43.770533 | 14.757800 | 58.473200 | 38.141700 | 37.316733 | 0.000000 | -1297.050967 | -967.195567 |
Real Price | 1177.380400 | 1340.821500 | 1311.808767 | 1355.524167 | 1335.192667 | 1334.367700 | 1297.050967 | 0.000000 | 329.855400 |
SP500 | 847.525000 | 1010.966100 | 981.953367 | 1025.668767 | 1005.337267 | 1004.512300 | 967.195567 | -329.855400 | 0.000000 |
[27]:
pr1.result.frame['euc_sim'].equals(pr2.result.frame['euc_sim'])
[27]:
False
As we can see, the parameter is being passed on correctly to euc_sim
.
Closing thoughts¶
This notebook illustrates how simple it is to create custom profilers and bundles.
It’s up to the user to mix and match whichever profilers are relevant to their needs, pre-canned ones available under tslumen.profile
or user-defined functions, provided they meet the conventions listed above and are decorated using @ProfilingFunction
.