def get_step_matrix(self, max_steps=None, plot_type=True, **kwargs):
        """
        Plots heatmap with distribution of events over event steps (ordering in the session by event time)

        :param max_steps: maximum number of steps to show
        :param plot_type: if True, then plot in interactive session (jupyter notebook)
        :return: pd.DataFrame with distribution of events over event order
        """
        target_event_list = self.retention_config['target_event_list']
        # TODO give filter, return to desc tables ???
        self._add_event_rank(**kwargs)
        agg = self.get_edgelist(
            cols=['event_rank', self.retention_config['event_col']],
            norm=False)
        if max_steps:
            agg = agg[agg.event_rank <= max_steps]
        agg.columns = ['event_rank', 'event_name', 'freq']
        tot_cnt = agg[agg['event_rank'] == 1].freq.sum()
        agg['freq'] = agg['freq'] / tot_cnt
        piv = agg.pivot(index='event_name',
                        columns='event_rank',
                        values='freq').fillna(0)
        piv.columns.name = None
        piv.index.name = None
        for i in target_event_list:
            piv = piv.append(self._add_accums(piv, i))
        piv = piv.round(2)
        if plot_type:
            plot.step_matrix(piv)
        return piv
    def get_step_matrix_difference(self, groups, plot_type=True, max_steps=30, **kwargs):
        """
        Plots heatmap with difference of events distributions over steps between two given groups

        :param groups: boolean vector that splits data in to groups
        :param plot_type: if True, then heatmap plot will be shown in interactive mode
        :param max_steps: maximum number of steps to show
        :return: pd.DataFrame with step matrix
        """
        desc_old = self._obj[~groups].copy().trajectory.get_step_matrix(plot_type=False, max_steps=max_steps, **kwargs)
        desc_new = self._obj[groups].copy().trajectory.get_step_matrix(plot_type=False, max_steps=max_steps, **kwargs)
        desc_old, desc_new = self._create_diff_index(desc_old, desc_new)
        desc_old, desc_new = self._diff_step_allign(desc_old, desc_new)
        diff = desc_new - desc_old
        diff = diff.sort_index(axis=1)
        if plot_type:
            plot.step_matrix(diff)
        return diff
    def get_step_matrix(self,
                        max_steps=None,
                        plot_type=True,
                        dt_means=False,
                        **kwargs):
        """
        Plots heatmap with distribution of events over event steps (ordering in the session by event time)

        :param max_steps: maximum number of steps to show
        :param plot_type: if True, then plot in interactive session (jupyter notebook)
        :return: pd.DataFrame with distribution of events over event order
        """
        target_event_list = self.retention_config['target_event_list']
        # TODO give filter, return to desc tables ???
        self._add_event_rank(**kwargs)
        agg = self.get_edgelist(
            cols=['event_rank', self.retention_config['event_col']],
            norm=False)
        if max_steps:
            agg = agg[agg.event_rank <= max_steps]
        agg.columns = ['event_rank', 'event_name', 'freq']
        tot_cnt = agg[agg['event_rank'] == 1].freq.sum()
        agg['freq'] = agg['freq'] / tot_cnt
        piv = agg.pivot(index='event_name',
                        columns='event_rank',
                        values='freq').fillna(0)
        piv.columns.name = None
        piv.index.name = None
        for i in target_event_list:
            piv = piv.append(self._add_accums(piv, i))
        piv = piv.round(2)
        if plot_type:
            plot.step_matrix(piv)
        if dt_means:
            means = np.array(
                self._obj.groupby('event_rank').apply(lambda x: np.exp(
                    np.mean(
                        np.log((x.next_timestamp - x.event_timestamp).dt.
                               total_seconds() + 1e-20)))))
            piv = pd.concat([
                piv,
                pd.DataFrame([means], columns=piv.columns, index=['dt_mean'])
            ])
        return piv