Example #1
0
        /// <summary>
        /// Initializes a new contingency table.
        /// </summary>
        /// <param name="rowValues">The low labels.</param>
        /// <param name="columnValues">The column labels.</param>
        public ContingencyTable(IReadOnlyCollection <R> rowValues, IReadOnlyCollection <C> columnValues)
        {
            if (rowValues == null)
            {
                throw new ArgumentNullException(nameof(rowValues));
            }
            if (columnValues == null)
            {
                throw new ArgumentNullException(nameof(columnValues));
            }

            rowMap = new NullableDictionary <R, int>();
            foreach (R rowValue in rowValues)
            {
                rowMap.Add(rowValue, rowMap.Count);
            }

            columnMap = new NullableDictionary <C, int>();
            foreach (C columnValue in columnValues)
            {
                columnMap.Add(columnValue, columnMap.Count);
            }

            counts  = new int[rowMap.Count, columnMap.Count];
            rCounts = new int[rowMap.Count];
            cCounts = new int[columnMap.Count];
            tCounts = 0;
        }
Example #2
0
 internal ContingencyTable(NullableDictionary <R, int> rowMap, NullableDictionary <C, int> columnMap, int[,] counts, int[] rCounts, int[] cCounts, int tCounts)
 {
     this.rowMap    = rowMap;
     this.columnMap = columnMap;
     this.counts    = counts;
     this.rCounts   = rCounts;
     this.cCounts   = cCounts;
     this.tCounts   = tCounts;
 }
Example #3
0
 internal KeyCollection(NullableDictionary <K, V> parent)
 {
     this.parent = parent;
 }
Example #4
0
        /// <summary>
        /// Produces a cross-tabulation.
        /// </summary>
        /// <typeparam name="R">The type of row data.</typeparam>
        /// <typeparam name="C">The type of column data</typeparam>
        /// <param name="rowValues">The data values for rows.</param>
        /// <param name="columnValues">The data values for columns.</param>
        /// <returns>A cross-tabular summary of the number of joint occurrences of each row and column value.</returns>
        public static ContingencyTable <R, C> Crosstabs <R, C> (IReadOnlyList <R> rowValues, IReadOnlyList <C> columnValues)
        {
            if (rowValues == null)
            {
                throw new ArgumentNullException(nameof(rowValues));
            }
            if (columnValues == null)
            {
                throw new ArgumentNullException(nameof(columnValues));
            }
            if (rowValues.Count != columnValues.Count)
            {
                throw new DimensionMismatchException();
            }

            // This is coded as a two passes over the data. The first pass determines
            // the distinct row and column values. The second pass determines the cell counts.
            // It's possible to do this in one pass, but we need auxiliary memory and/or
            // dynamic storage and the details become messier.

            // Determine the distinct row and column values
            NullableDictionary <R, int> rowMap    = new NullableDictionary <R, int>();
            NullableDictionary <C, int> columnMap = new NullableDictionary <C, int>();

            for (int i = 0; i < rowValues.Count; i++)
            {
                R rowValue    = rowValues[i];
                C columnValue = columnValues[i];

                if (!rowMap.ContainsKey(rowValue))
                {
                    rowMap.Add(rowValue, rowMap.Count);
                }
                if (!columnMap.ContainsKey(columnValue))
                {
                    columnMap.Add(columnValue, columnMap.Count);
                }
            }

            // Fill out the cells and marginal totals
            int[,] counts = new int[rowMap.Count, columnMap.Count];
            int[] rowCounts    = new int[rowMap.Count];
            int[] columnCounts = new int[columnMap.Count];
            int   totalCount   = 0;

            for (int i = 0; i < rowValues.Count; i++)
            {
                R rowValue    = rowValues[i];
                C columnValue = columnValues[i];

                int rowIndex    = rowMap[rowValue];
                int columnIndex = columnMap[columnValue];

                counts[rowIndex, columnIndex]++;
                rowCounts[rowIndex]++;
                columnCounts[columnIndex]++;
                totalCount++;
            }

            return(new ContingencyTable <R, C>(rowMap, columnMap, counts, rowCounts, columnCounts, totalCount));
        }