public DynamicFormulaMeasure(string formula, IPivotData pvtData)
        {
            Parser  = new LambdaParser();
            Formula = formula;
            var formulaExpr   = Parser.Parse(formula);
            var formulaParams = LambdaParser.GetExpressionParameters(formulaExpr);

            var paramMeasureIndexes = new List <int>();
            var paramMeasureNames   = new List <string>();

            foreach (var fParam in formulaParams)
            {
                if (paramMeasureNames.Contains(fParam.Name))
                {
                    continue;                     // avoid duplicates
                }
                var paramMsrIdx = ResolveAggregatorIndex(fParam.Name, pvtData);
                if (paramMsrIdx >= 0)
                {
                    paramMeasureIndexes.Add(paramMsrIdx);
                    paramMeasureNames.Add(fParam.Name);
                }
            }

            ArgMeasureIndexes = paramMeasureIndexes.ToArray();
            ParamNameToArgIdx = new Dictionary <string, int>();
            for (int i = 0; i < paramMeasureNames.Count; i++)
            {
                ParamNameToArgIdx[paramMeasureNames[i]] = i;
            }
        }
 /// <summary>
 /// Initializes new slicing query to specified <see cref="PivotData"/> instance.
 /// </summary>
 /// <param name="pvtData">multidimensional dataset to query</param>
 public SliceQuery(IPivotData pvtData)
 {
     PvtData        = pvtData;
     DimSelectors   = new List <DimensionSelector>();
     AggrSelectors  = new List <AggregatorSelector>();
     FilterHandlers = new List <Func <KeyValuePair <object[], IAggregator>, bool> >();
 }
 public FilterPivotData(string[] dims, IAggregatorFactory aggr, IPivotData origPvtData,
                        Func <KeyValuePair <object[], IAggregator>, bool> filterHandler,
                        Func <KeyValuePair <object[], IAggregator>, object[]> keyHandler,
                        Func <KeyValuePair <object[], IAggregator>, IAggregator> aggrHandler)
 {
     Dims          = dims;
     Aggr          = aggr;
     PvtData       = origPvtData;
     FilterHandler = filterHandler;
     KeyHandler    = keyHandler;
     AggrHandler   = aggrHandler;
 }
        PivotData GetGrandTotalPvtData(IPivotData basePvtData)
        {
            // this is grand-total
            var grandTotalPvtData = new PivotData(emptyStringArray, PvtData.AggregatorFactory);
            var grandTotalAggr    = grandTotalPvtData[emptyObjectArray];

            foreach (var entry in basePvtData)
            {
                grandTotalAggr.Merge(entry.Value);
            }
            return(grandTotalPvtData);
        }
 /// <summary>
 /// Initializes new instance of <see cref="PivotTable"/> instance by specified <see cref="PivotData"/>
 /// </summary>
 /// <param name="axes">list of axes determined by dimensions</param>
 /// <param name="dataCube">multidimensional dataset used for calculating pivot table</param>
 /// <param name="axesComparers">list of custom comparers for sorting axes keys</param>
 public PivotTableMD(string[][] axes, IPivotData pvtData, IComparer <ValueKey>[] axesComparers)
 {
     Axes        = axes;
     PvtData     = pvtData;
     AxesIndexes = axes.Select(axis => GetDimIdx(axis)).ToArray();
     AxesKeys    = new ValueKey[Axes.Length][];
     for (int i = 0; i < Axes.Length; i++)
     {
         AxesKeys[i] = GetAxisKeys(i,
                                   axesComparers != null && i < axesComparers.Length && axesComparers[i] != null ? axesComparers[i] : NaturalSortKeyComparer.Instance);
     }
 }
 internal TotalsCachePivotData(IPivotData pvtData)
 {
     PvtData = pvtData;
     if (pvtData.Dimensions.Length <= 64)
     {
         GetValueHandler = new UlongMaskCache(this).Get;
     }
     else
     {
         GetValueHandler = new BitArrayMaskCache(this).Get;
     }
 }
Beispiel #7
0
 internal PivotDataMember(IPivotData pvtData, string[] aggrNames)
 {
     PvtData  = pvtData;
     DimToIdx = new Dictionary <string, int>(pvtData.Dimensions.Length);
     for (int i = 0; i < pvtData.Dimensions.Length; i++)
     {
         DimToIdx[pvtData.Dimensions[i]] = i;
     }
     AggrToIdx = new Dictionary <string, int>(aggrNames.Length);
     for (int i = 0; i < aggrNames.Length; i++)
     {
         AggrToIdx[aggrNames[i]] = i;
     }
 }
Beispiel #8
0
        /// <summary>
        /// Processes data from the specified <see cref="IPivotData"/> instance and calculates <see cref="PivotData"/> values
        /// </summary>
        /// <param name="data">input data represented by <see cref="IPivotData"/> instance</param>
        /// <param name="aggregatorNames">field names for accessing aggregator values</param>
        /// <remarks>
        /// This overload allows to use values of another data cube as input.
        /// <example>
        /// Lets assume that we need to calculate average over values that are calculated in another cube:
        /// <code>
        /// IPivotData sourcePvtData; // dimensions: "month", "store" and one sum measure
        /// var pvtData = new PivotData(new[] {"store"}, new AverageAggregatorFactory("value") );
        /// pvtData.ProcessData(sourcePvtData, "value");
        /// </code>
        /// </example>
        /// </remarks>
        public void ProcessData(IPivotData data, params string[] aggregatorNames)
        {
            var aggrCount = 1;

            if (data.AggregatorFactory is CompositeAggregatorFactory)
            {
                aggrCount = ((CompositeAggregatorFactory)data.AggregatorFactory).Factories.Length;
            }
            if (aggregatorNames.Length > aggrCount)
            {
                throw new ArgumentOutOfRangeException("Number of aggregators is less than number of provided names.");
            }
            var pvtDataMember = new PivotDataMember(data, aggregatorNames);

            ProcessData(data, pvtDataMember.GetValue);
        }
        /// <summary>
        /// Initializes a new instance of <see cref="PivotTable"/> instance by specified <see cref="PivotData"/>
        /// </summary>
        /// <param name="rows">list of dimensions for determining table rows</param>
        /// <param name="columns">list of dimensions for determining table columns</param>
        /// <param name="pvtData">multidimensional dataset used for pivot table calculation</param>
        /// <param name="rowKeysComparer">custom table row keys comparer (if null <see cref="NaturalSortKeyComparer"/> is used)</param>
        /// <param name="colKeysComparer">custom table row keys comparer (if null <see cref="NaturalSortKeyComparer"/> is used)</param>
        public PivotTable(string[] rows, string[] columns, IPivotData pvtData, IComparer <ValueKey> rowKeysComparer, IComparer <ValueKey> colKeysComparer)
        {
            PreserveGroupOrder = false;
            TotalsCache        = true;
            Columns            = columns ?? new string[0];
            Rows               = rows ?? new string[0];
            PvtData            = pvtData;
            TotalsCachePvtData = new TotalsCachePivotData(pvtData);
            ColumnIndexes      = GetDimIdx(Columns);
            RowIndexes         = GetDimIdx(Rows);
            AlwaysHasEmpty     = ColumnIndexes.Union(RowIndexes).Count() < PvtData.Dimensions.Length;
            IsMultiValue       = pvtData.AggregatorFactory is CompositeAggregatorFactory;

            GenerateAxesKeys();

            SortKeys(ColumnKeys, Columns, colKeysComparer ?? NaturalSortKeyComparer.Instance);
            SortKeys(RowKeys, Rows, rowKeysComparer ?? NaturalSortKeyComparer.Instance);
        }
        /// <summary>
        /// Returns unique keys of specified dimensions for the <see cref="IPivotData"/> instance.
        /// </summary>
        /// <param name="pvtData"><see cref="IPivotData"/> instance</param>
        /// <param name="dims">list of dimensions</param>
        /// <param name="dimSortComparers">list of comparers that should be used for sorting dimension keys</param>
        /// <returns>array of keys for specified dimensions</returns>
        public static object[][] GetDimensionKeys(IPivotData pvtData, string[] dims, IComparer <object>[] dimSortComparers)
        {
            if (dims == null)
            {
                dims = pvtData.Dimensions;
            }
            var dimLen     = dims.Length;
            var dimKeysArr = new object[dimLen][];
            var dimKeys    = new HashSet <object> [dimLen];
            var dimIndexes = new int[dimLen];
            int d;

            for (d = 0; d < dimLen; d++)
            {
                var dimIdx = Array.IndexOf(pvtData.Dimensions, dims[d]);
                if (dimIdx < 0)
                {
                    throw new ArgumentOutOfRangeException("dims", String.Format("Unknown dimension: {0}", dims[d]));
                }
                dimIndexes[d] = dimIdx;
                dimKeys[d]    = new HashSet <object>();
            }
            foreach (var entry in pvtData)
            {
                for (d = 0; d < dimLen; d++)
                {
                    dimKeys[d].Add(entry.Key[dimIndexes[d]]);
                }
            }

            for (d = 0; d < dims.Length; d++)
            {
                dimKeysArr[d] = new object[dimKeys[d].Count];
                dimKeys[d].CopyTo(dimKeysArr[d]);
                if (dimSortComparers != null)
                {
                    // apply sort
                    Array.Sort(dimKeysArr[d],
                               d < dimSortComparers.Length && dimSortComparers[d] != null ?
                               dimSortComparers[d] : NaturalSortKeyComparer.Instance);
                }
            }
            return(dimKeysArr);
        }
        int ResolveAggregatorIndex(string name, IPivotData pvtData)
        {
            var aggrFactories = pvtData.AggregatorFactory is CompositeAggregatorFactory ?
                                ((CompositeAggregatorFactory)pvtData.AggregatorFactory).Factories :
                                new [] { pvtData.AggregatorFactory };

            for (int i = 0; i < aggrFactories.Length; i++)
            {
                var indexBasedName = "value" + i.ToString();
                if (name == indexBasedName)
                {
                    return(i);
                }
                var aggrFactoryName = aggrFactories[i].ToString().ToLower().Replace(" ", "");
                if (name == aggrFactoryName)
                {
                    return(i);
                }
            }
            return(-1);
        }
        PivotData GetReducedPivotData(IPivotData basePvtData, object[] key, int emptyDims)
        {
            if (emptyDims == key.Length)
            {
                // this is grand-total
                return(GetGrandTotalPvtData(basePvtData));
            }
            var sliceQuery = new SliceQuery(basePvtData);

            for (int i = 0; i < key.Length; i++)
            {
                if (Key._Empty != key[i])
                {
                    sliceQuery.Dimension(PvtData.Dimensions[i]);
                }
            }
            var reducedPvtData = sliceQuery.Execute();

            reducedPvtData.LazyAdd = false;
            return(reducedPvtData);
        }
        DataTable getPivotDataAsTable(IPivotData pvtData)
        {
            var tbl = new DataTable();

            // create columns by pivot data
            foreach (var dim in pvtData.Dimensions)
            {
                tbl.Columns.Add(dim, typeof(object));
            }
            if (pvtData.AggregatorFactory is CompositeAggregatorFactory)
            {
                var aggrFactories = ((CompositeAggregatorFactory)pvtData.AggregatorFactory).Factories;
                for (int i = 0; i < aggrFactories.Length; i++)
                {
                    tbl.Columns.Add(String.Format("value_{0}", i), typeof(object));
                }
            }
            else
            {
                tbl.Columns.Add("value", typeof(object));
            }
            // add rows
            foreach (var entry in pvtData)
            {
                var vals = new object[tbl.Columns.Count];
                for (int i = 0; i < entry.Key.Length; i++)
                {
                    vals[i] = entry.Key[i];
                }
                var aggr = entry.Value.AsComposite();
                for (int i = 0; i < aggr.Aggregators.Length; i++)
                {
                    vals[entry.Key.Length + i] = aggr.Aggregators[i].Value;
                }
                tbl.Rows.Add(vals);
            }

            tbl.AcceptChanges();
            return(tbl);
        }
Beispiel #14
0
        /// <summary>
        /// Modifies the current <see cref="PivotData"/> object to merge values from itself and specified <see cref="PivotData"/>.
        /// </summary>
        /// <remarks>
        /// Only compatible <see cref="PivotData"/> objects could be merged: they should have the same AggregatorFactory and Dimensions configuration.
        /// This method is also useful for organizing parallel data aggregation algorithm.
        /// </remarks>
        /// <param name="pvtData">multidimensional dataset to merge</param>
        public virtual void Merge(IPivotData pvtData)
        {
            if (!AggregatorFactory.Equals(pvtData.AggregatorFactory))
            {
                throw new ArgumentException("AggregatorFactory mismatch");
            }
            if (Dimensions.Length != pvtData.Dimensions.Length)
            {
                throw new ArgumentException("Dimensions mismatch");
            }
            for (int i = 0; i < Dimensions.Length; i++)
            {
                if (!Dimensions[i].SequenceEqual(pvtData.Dimensions[i]))
                {
                    throw new ArgumentException(String.Format("Dimension {0} elements mismatch", i));
                }
            }

            // remove all totals
            totalValues.Clear();
            valuesArr = null;

            IAggregator aggr;

            foreach (var dp in pvtData)
            {
                if (!values.TryGetValue(dp.Key, out aggr))
                {
                    aggr           = aggregatorFactory.Create();
                    values[dp.Key] = aggr;
                }
                aggr.Merge(dp.Value);
            }
            if (!lazyTotals)
            {
                BatchCalcTotals();
            }
        }
        public PivotDataState(IPivotData pvtData)
        {
            var  allRawKeys = new List <object>();
            var  keyIdx = new Dictionary <object, uint>(pvtData.Count);
            var  allVkRefs = new uint[pvtData.Count][];
            var  allRawVals = new object[pvtData.Count];
            uint i, idx;
            int  dimCnt = pvtData.Dimensions.Length;

            object[] vk;

            int valIdx = 0;

            foreach (var entry in pvtData)
            {
                vk = entry.Key;

                var vkIdx = new uint[dimCnt];
                for (i = 0; i < dimCnt; i++)
                {
                    if (!keyIdx.TryGetValue(vk[i], out idx))
                    {
                        idx = (uint)allRawKeys.Count;
                        allRawKeys.Add(vk[i]);
                        keyIdx[vk[i]] = idx;
                    }
                    vkIdx[i] = idx;
                }
                allVkRefs[valIdx]  = vkIdx;
                allRawVals[valIdx] = entry.Value.GetState();
                valIdx++;
            }

            DimCount  = (uint)dimCnt;
            KeyValues = allRawKeys.ToArray();
            ValueKeys = allVkRefs;
            Values    = allRawVals;
        }
 /// <summary>
 /// Initializes new instance of <see cref="PivotTable"/> instance by specified <see cref="PivotData"/>
 /// </summary>
 /// <param name="axes">list of axes determined by dimensions</param>
 /// <param name="pvtData">multidimensional dataset used for pivot table calculation</param>
 public PivotTableMD(string[][] axes, IPivotData pvtData) : this(axes, pvtData, null)
 {
 }
Beispiel #17
0
 /// <summary>
 /// Initializes a new instance of <see cref="PivotTable"/> instance by specified <see cref="PivotData"/>
 /// </summary>
 /// <param name="rows">list of dimensions for determining table rows</param>
 /// <param name="columns">list of dimensions for determining table columns</param>
 /// <param name="pvtData">multidimensional dataset used for pivot table calculation</param>
 public PivotTable(string[] rows, string[] columns, IPivotData pvtData) : this(rows, columns, pvtData, null, null)
 {
 }