コード例 #1
0
        public static ICube MergeQuick(this ICube baseCube, ICube otherCube)
        {
            if (!Enumerable.SequenceEqual(baseCube.DataTypes.Keys, otherCube.DataTypes.Keys) ||
                !Enumerable.SequenceEqual(baseCube.DataTypes.Values, otherCube.DataTypes.Values))
            {
                throw new Exception("Cubes must be of same type to be merged");
            }

            var o = new ResultCube();

            o.Initialize(baseCube.DataTypes);
            var baseRows  = baseCube.GetAllRows().ToArray();
            var otherRows = otherCube.GetAllRows().ToArray();

            for (var i = 0; i < baseRows.Length; i++)
            {
                var br = baseRows[i];
                o.AddRow(br.MetaData, br.Value);
            }

            for (var i = 0; i < otherRows.Length; i++)
            {
                var br = otherRows[i];
                o.AddRow(br.MetaData, br.Value);
            }

            return(o);
        }
コード例 #2
0
        /// <summary>
        /// Differences two cubes, assuming same number and same order of rows in both
        /// </summary>
        /// <param name="baseCube"></param>
        /// <param name="cubeToSubtract"></param>
        /// <returns></returns>
        public static ICube QuickDifference(this ICube baseCube, ICube cubeToSubtract)
        {
            if (!Enumerable.SequenceEqual(baseCube.DataTypes.Keys, cubeToSubtract.DataTypes.Keys) ||
                !Enumerable.SequenceEqual(baseCube.DataTypes.Values, cubeToSubtract.DataTypes.Values))
            {
                throw new Exception("Cubes must be of same type to be differenced");
            }

            var o = new ResultCube();

            o.Initialize(baseCube.DataTypes);
            var baseRows = baseCube.GetAllRows().ToArray();
            var subRows  = cubeToSubtract.GetAllRows().ToArray();

            if (baseRows.Length != subRows.Length)
            {
                throw new Exception("Cubes must have same number of rows to quick-diff them");
            }

            for (var i = 0; i < baseRows.Length; i++)
            {
                var br = baseRows[i];
                var sr = subRows[i];
                o.AddRow(br.MetaData, br.Value - sr.Value);
            }

            return(o);
        }
コード例 #3
0
        public static ICube Sort(this ICube cube, List <string> fieldsToSortOn)
        {
            foreach (var fieldToSortOn in fieldsToSortOn)
            {
                if (!cube.DataTypes.ContainsKey(fieldToSortOn))
                {
                    throw new Exception($"Cannot sort on field {fieldToSortOn} as it is not present");
                }
            }

            var outCube = new ResultCube();

            outCube.Initialize(cube.DataTypes);

            var fieldNames = cube.DataTypes.Keys.ToList();
            var indexes    = fieldsToSortOn.Select(x => fieldNames.IndexOf(x)).Reverse();

            var rows = new List <ResultCubeRow>(cube.GetAllRows());

            foreach (var ix in indexes)
            {
                rows = rows.OrderBy(x => x.MetaData[ix]).ToList();
            }

            foreach (var row in rows)
            {
                outCube.AddRow(row.MetaData, row.Value);
            }

            return(outCube);
        }
コード例 #4
0
        public static ICube Filter(this ICube cube, List <KeyValuePair <string, object> > fieldsToFilterOn, bool filterOut = false)
        {
            foreach (var fieldToFilterOn in fieldsToFilterOn.Select(x => x.Key))
            {
                if (!cube.DataTypes.ContainsKey(fieldToFilterOn))
                {
                    throw new Exception($"Cannot filter on field {fieldToFilterOn} as it is not present");
                }
            }

            var outCube = new ResultCube();

            outCube.Initialize(cube.DataTypes);

            var fieldNames = cube.DataTypes.Keys.ToList();
            var indexes    = fieldsToFilterOn
                             .Select(x => x.Key)
                             .Distinct()
                             .ToDictionary(x => x, x => fieldNames.IndexOf(x));
            var values = new Dictionary <string, List <object> >();

            foreach (var kv in fieldsToFilterOn)
            {
                if (!values.ContainsKey(kv.Key))
                {
                    values[kv.Key] = new List <object> {
                        kv.Value
                    }
                }
                ;
                else
                {
                    values[kv.Key].Add(kv.Value);
                }
            }

            foreach (var row in cube.GetAllRows())
            {
                var rowIsRelevant = true;
                foreach (var kv in values)
                {
                    if (!kv.Value.Any(v => IsEqual(row.MetaData[indexes[kv.Key]], v)))
                    {
                        rowIsRelevant = false;
                        break;
                    }
                }
                if (filterOut)
                {
                    rowIsRelevant = !rowIsRelevant;
                }

                if (rowIsRelevant)
                {
                    outCube.AddRow(row.MetaData, row.Value);
                }
            }

            return(outCube);
        }
コード例 #5
0
        public static ICube BucketTimeAxis(this ICube cube, string timeFieldName, string bucketedFieldName, Dictionary <DateTime, string> bucketBoundaries)
        {
            if (!cube.DataTypes.ContainsKey(timeFieldName))
            {
                throw new Exception($"Cannot filter on field {timeFieldName} as it is not present");
            }

            var outCube  = new ResultCube();
            var newTypes = new Dictionary <string, Type>(cube.DataTypes);

            newTypes.Add(bucketedFieldName, typeof(string));
            outCube.Initialize(newTypes);

            var buckets       = bucketBoundaries.Keys.OrderBy(x => x).ToList();
            var bucketFieldIx = cube.GetColumnIndex(timeFieldName);

            foreach (var row in cube.GetAllRows())
            {
                var date   = (DateTime)row.MetaData[bucketFieldIx];
                var bucket = buckets.BinarySearch(date);
                if (bucket < 0)
                {
                    bucket = ~bucket;
                }
                var bucketLabel = bucketBoundaries[buckets[bucket]];

                var metaList = new List <object>(row.MetaData)
                {
                    bucketLabel
                };
                outCube.AddRow(metaList.ToArray(), row.Value);
            }

            return(outCube);
        }
コード例 #6
0
        public static ICube Difference(this ICube baseCube, ICube cubeToSubtract)
        {
            if (!Enumerable.SequenceEqual(baseCube.DataTypes.Keys, cubeToSubtract.DataTypes.Keys) ||
                !Enumerable.SequenceEqual(baseCube.DataTypes.Values, cubeToSubtract.DataTypes.Values))
            {
                throw new Exception("Cubes must be of same type to be differenced");
            }

            var o = new ResultCube();

            o.Initialize(baseCube.DataTypes);
            var baseRows = baseCube.GetAllRows().ToList();
            var subRows  = cubeToSubtract.GetAllRows().ToList();

            foreach (var br in baseRows)
            {
                var rowFound = false;
                foreach (var sr in subRows)
                {
                    if (Enumerable.SequenceEqual(br.MetaData, sr.MetaData))
                    {
                        o.AddRow(br.MetaData, br.Value - sr.Value);
                        subRows.Remove(sr);
                        rowFound = true;
                        break;
                    }
                }

                if (!rowFound) //zero to subtract
                {
                    o.AddRow(br.MetaData, br.Value);
                }
            }

            //look at what is left in subrows
            foreach (var sr in subRows)
            {
                o.AddRow(sr.MetaData, -sr.Value);
            }

            return(o);
        }
コード例 #7
0
        public static ICube ScalarMultiply(this ICube cube, double scalar)
        {
            var outCube = new ResultCube();

            outCube.Initialize(cube.DataTypes);
            var rows = new List <ResultCubeRow>(cube.GetAllRows());

            foreach (var row in rows)
            {
                outCube.AddRow(row.MetaData, row.Value * scalar);
            }

            return(outCube);
        }
コード例 #8
0
        public static ICube Filter(this ICube cube, Dictionary <string, object> fieldsToFilterOn, bool filterOut = false)
        {
            foreach (var fieldToFilterOn in fieldsToFilterOn.Keys)
            {
                if (!cube.DataTypes.ContainsKey(fieldToFilterOn))
                {
                    throw new Exception($"Cannot filter on field {fieldToFilterOn} as it is not present");
                }
            }

            var outCube = new ResultCube();

            outCube.Initialize(cube.DataTypes);

            var fieldNames = cube.DataTypes.Keys.ToList();
            var indexes    = fieldsToFilterOn.Keys.ToDictionary(x => x, x => fieldNames.IndexOf(x));

            foreach (var row in cube.GetAllRows())
            {
                var rowIsRelevant = true;
                foreach (var kv in fieldsToFilterOn)
                {
                    if (!IsEqual(row.MetaData[indexes[kv.Key]], Convert.ChangeType(kv.Value, cube.DataTypes[kv.Key])))
                    {
                        rowIsRelevant = false;
                        break;
                    }
                }
                if (filterOut)
                {
                    rowIsRelevant = !rowIsRelevant;
                }

                if (rowIsRelevant)
                {
                    outCube.AddRow(row.MetaData, row.Value);
                }
            }

            return(outCube);
        }
コード例 #9
0
        public static ICube Sort(this ICube cube)
        {
            var outCube = new ResultCube();

            outCube.Initialize(cube.DataTypes);

            var fieldNames = cube.DataTypes.Keys.ToList();
            var indexes    = Enumerable.Range(0, fieldNames.Count).Reverse().ToArray();
            var rows       = new List <ResultCubeRow>(cube.GetAllRows());

            foreach (var ix in indexes)
            {
                rows = rows.OrderBy(x => x.MetaData[ix]).ToList();
            }

            foreach (var row in rows)
            {
                outCube.AddRow(row.MetaData, row.Value);
            }

            return(outCube);
        }
コード例 #10
0
        public static ICube Pivot(this ICube cube, string[] fieldsToAggregateBy, AggregationAction aggregationAction)
        {
            //for now, aggregate only works on numerical fields and performs a sum
            foreach (var fieldToAggregateBy in fieldsToAggregateBy)
            {
                if (!cube.DataTypes.ContainsKey(fieldToAggregateBy))
                {
                    throw new Exception($"Cannot aggregate on field {fieldToAggregateBy} as it is not present");
                }
            }

            var types = cube.DataTypes.Keys.ToList();
            var ixs   = fieldsToAggregateBy.Select(f => types.IndexOf(f)).ToArray();

            var rows           = cube.GetAllRows();
            var distinctValues = rows.Select(x => string.Join("~", ixs.Select(ix => x.MetaData[ix]?.ToString() ?? string.Empty))).Distinct();

            var outCube = new ResultCube();
            var oT      = new Dictionary <string, Type>();

            foreach (var fieldToAggregateBy in fieldsToAggregateBy)
            {
                oT.Add(fieldToAggregateBy, cube.DataTypes[fieldToAggregateBy]);
            }
            outCube.Initialize(oT);
            var aggData      = new Dictionary <string, double>();
            var aggDataCount = new Dictionary <string, int>();
            var metaDict     = new Dictionary <string, object[]>();

            foreach (var row in rows)
            {
                var rowKey = string.Join("~", ixs.Select(i => row.MetaData[i]?.ToString() ?? string.Empty));
                if (!aggData.ContainsKey(rowKey))
                {
                    if (aggregationAction == AggregationAction.Min)
                    {
                        aggData[rowKey] = double.MaxValue;
                    }
                    else if (aggregationAction == AggregationAction.Max)
                    {
                        aggData[rowKey] = double.MinValue;
                    }
                    else
                    {
                        aggData[rowKey] = 0;
                    }
                    aggDataCount[rowKey] = 0;
                    var filetedMetaData = new object[ixs.Length];
                    for (var i = 0; i < ixs.Length; i++)
                    {
                        filetedMetaData[i] = row.MetaData[ixs[i]];
                    }
                    metaDict[rowKey] = filetedMetaData;
                }
                switch (aggregationAction)
                {
                case AggregationAction.Sum:
                    aggData[rowKey] += row.Value;
                    break;

                case AggregationAction.Average:
                    aggData[rowKey] += row.Value;
                    aggDataCount[rowKey]++;
                    break;

                case AggregationAction.Min:
                    aggData[rowKey] = System.Math.Min(aggData[rowKey], row.Value);
                    break;

                case AggregationAction.Max:
                    aggData[rowKey] = System.Math.Max(aggData[rowKey], row.Value);
                    break;
                }
            }

            //final post-processing for average
            foreach (var rowKey in aggData.Keys.ToList())
            {
                var rowDict = new Dictionary <string, object>();
                if (aggregationAction == AggregationAction.Average)
                {
                    aggData[rowKey] /= aggDataCount[rowKey];
                }

                outCube.AddRow(metaDict[rowKey], aggData[rowKey]);
            }


            return(outCube);
        }
コード例 #11
0
        public static ICube Merge(this ICube baseCube, ICube otherCube)
        {
            //add check that common fields are of them same type...
            foreach (var kv in baseCube.DataTypes.Where(x => otherCube.DataTypes.Keys.Contains(x.Key)))
            {
                if (kv.Value != otherCube.DataTypes[kv.Key])
                {
                    throw new Exception($"Data types dont match for field {kv.Key}");
                }
            }


            var newDataTypes = new Dictionary <string, Type>();

            foreach (var kv in baseCube.DataTypes)
            {
                newDataTypes[kv.Key] = kv.Value;
            }
            foreach (var kv in otherCube.DataTypes)
            {
                newDataTypes[kv.Key] = kv.Value;
            }


            var o = new ResultCube();

            o.Initialize(newDataTypes);
            var baseRows  = baseCube.GetAllRows().ToArray();
            var otherRows = otherCube.GetAllRows().ToArray();

            var baseIx  = baseCube.DataTypes.Keys.Select(k => o.GetColumnIndex(k)).ToArray();
            var otherIx = otherCube.DataTypes.Keys.Select(k => o.GetColumnIndex(k)).ToArray();

            var cleanRow = o.DataTypes.Select(kv => GetDefaultValue(kv.Value)).ToArray();

            for (var i = 0; i < baseRows.Length; i++)
            {
                var row = new object[cleanRow.Length];
                Array.Copy(cleanRow, row, row.Length);
                var br = baseRows[i];
                for (var j = 0; j < baseIx.Length; j++)
                {
                    row[baseIx[j]] = br.MetaData[j];
                }
                o.AddRow(row, br.Value);
            }

            for (var i = 0; i < otherRows.Length; i++)
            {
                var br  = otherRows[i];
                var row = new object[cleanRow.Length];
                Array.Copy(cleanRow, row, row.Length);
                for (var j = 0; j < baseIx.Length; j++)
                {
                    row[baseIx[j]] = br.MetaData[j];
                }
                o.AddRow(row, br.Value);
            }

            return(o);
        }