Exemplo n.º 1
0
        /// <summary>
        /// Groups the data by the values in the given column, and computes aggregate quantities for each group.
        /// </summary>
        /// <param name="groupByColumnName">The name of the column to group by.</param>
        /// <param name="aggregator">A function that computes the aggregate quantities.</param>
        /// <returns>A new data frame containing the aggregates for each group.</returns>
        /// <remarks>
        /// <para>The first column of the returned <see cref="FrameTable"/> has the same name as the
        /// original <paramref name="groupByColumnName"/> and contains all the distinct
        /// values of that column in the original view. There is an additional column for each
        /// dictionary entry returned by <paramref name="aggregator"/>, whose name is the returned
        /// key and whose values are values returned for each group.</para>
        /// <para>The function that computes the aggregate receives a <see cref="FrameView"/> containing
        /// all the rows in the group. To produce aggregate results, it can use values in any of
        /// the columns. Each invocation of the <paramref name="aggregator"/> must return the same keys
        /// and values for the same keys must be of the same type. (Values for different keys may be
        /// of different types.) Aggregate column names are taken from the keys and storage types are
        /// inferred from the returned values.</para>
        /// <para>To produce just one aggregate value, you may find it simpler and more efficient
        /// to use the <see cref="GroupBy(string, Func{FrameView, IReadOnlyDictionary{string, object}})"/>
        /// overload.</para>
        /// </remarks>
        public FrameTable GroupBy(string groupByColumnName, Func <FrameView, IReadOnlyDictionary <string, object> > aggregator)
        {
            // Collect rows into groups.
            int       groupByColumnIndex = GetColumnIndex(groupByColumnName);
            NamedList groupByColumn      = columns[groupByColumnIndex];
            NullableDictionary <object, List <int> > groups = FindGroups(groupByColumn);

            // Create a column to hold the group values.
            NamedList groupsColumn = NamedList.Create(groupByColumnName, groupByColumn.StorageType);

            // Create an enumerator that feeds the groups into the aggregator and presents them as dictionaries.
            IEnumerable <IReadOnlyDictionary <string, object> > aggregatesEnumerator = GetGroupEnumerator(groups, aggregator, groupsColumn);

            // Column-ify and validate the presented dictionaries.
            List <NamedList> aggregateColumns = DictionaryHelper.ReadDictionaries(aggregatesEnumerator);

            // Collect the results into a frame table.
            FrameTable result = new FrameTable();

            // First column is the group values.
            result.AddColumn(groupsColumn);
            // Remaining columns are aggregate columns.
            foreach (NamedList aggregateColumn in aggregateColumns)
            {
                result.AddColumn(aggregateColumn);
            }
            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Constructs a new frame table from a sequence of dictionaries.
        /// </summary>
        /// <param name="dictionaries">A enumerable set of dictionaries, one for each row, whose
        /// keys are the column names and whose values are the cell value of the column for that row.</param>
        /// <returns>A new frame table with data from the dictionaries.</returns>
        /// <remarks><para>The storage type of each column is inferred from the types of objects
        /// encountered are the frame table is constructed.</para></remarks>
        public static FrameTable FromDictionaries(IEnumerable <IReadOnlyDictionary <string, object> > dictionaries)
        {
            if (dictionaries == null)
            {
                throw new ArgumentNullException(nameof(dictionaries));
            }

            List <NamedList> columns = DictionaryHelper.ReadDictionaries(dictionaries);

            // Collect the results into a frame table.
            FrameTable result = new FrameTable(columns);

            return(result);
        }