Aggregates single function
        :param values: list of objects (dict)
        :param agg_field: target field to calculate aggregate
        :param agg_func: aggregate function
        :param group_by: field used to determine group
        :return: aggregated value

def agg_single_func(values, agg_field, agg_func, group_by=None):
        """
        Aggregates single function
        :param values: list of objects (dict)
        :param agg_field: target field to calculate aggregate
        :param agg_func: aggregate function
        :param group_by: field used to determine group
        :return: aggregated value
        """
        if len(values) == 0:
            return None
        else:
            if group_by:
                group_aggs = pd.DataFrame(values).groupby(group_by).agg({agg_field: [agg_func]})
                res = {}
                for row in group_aggs.itertuples():
                    res.update({row[0]: row[1]})
                return res
            else:
                return pd.DataFrame(values).agg({agg_field: [agg_func]})[agg_field][agg_func]