public ColumnStats GetDomainValueBarChart(int domainColumn, int dataColumn, int denominatorColumn, StatTypes statType) { CheckState(); var stats = new ColumnStats(); stats.Computed = true; var domainIdList = new Dictionary<string, int>(); stats.DomainValues = GetDomainValues(domainColumn); stats.Buckets = stats.DomainValues.Length; stats.Histogram = new double[stats.Buckets]; stats.TargetColumn = dataColumn; stats.DomainColumn = domainColumn; stats.DomainStatType = statType; stats.DemoninatorColumn = denominatorColumn; var sortLists = new List<double>[stats.Buckets]; var min = new double[stats.Buckets]; var max = new double[stats.Buckets]; var sum = new double[stats.Buckets]; var denominatorSum = new double[stats.Buckets]; stats.Selected = new bool[stats.Buckets]; for (var i = 0; i < stats.Buckets; i++) { domainIdList.Add(stats.DomainValues[i], i); max[i] = double.MinValue; min[i] = double.MaxValue; sortLists[i] = new List<double>(); stats.Selected[i] = false; } table.Lock(); // First Pass - Basic statistics.. foreach (var row in table.Rows) { var selected = Filters.Count == 0; var firstFilter = true; foreach (var fgt in Filters) { var filter = fgt.Stats; if (filter.Computed && (selected || firstFilter)) { if (filter.IsSelected(row)) { selected = true; } else { selected = false; } firstFilter = false; } } if (selected) { try { if (dataColumn > -1) { var domainID = domainIdList[row[domainColumn]]; var sucsess = false; double val = 0; sucsess = double.TryParse(row[dataColumn], out val); if (sucsess) { if (val > max[domainID]) { max[domainID] = val; } if (val < min[domainID]) { min[domainID] = val; } stats.Count++; stats.Sum += val; sum[domainID] += val; sortLists[domainID].Add(val); } else if (statType == StatTypes.Count) // && domainColumn == dataColumn) { sortLists[domainID].Add(0); } if (statType == StatTypes.Ratio && denominatorColumn != -1) { sucsess = double.TryParse(row[denominatorColumn], out val); if (sucsess) { denominatorSum[domainID] += val; } } } } catch { } } } table.Unlock(); //2nd pass does not use the table anymore. working from sortList for (var i = 0; i < stats.Buckets; i++) { if (sortLists[i].Count > 0) { var average = sum[i] / sortLists[i].Count; double median = 0; sortLists[i].Sort(); var midPoint = Math.Max(0, (sortLists[i].Count / 2) - 1); try { if (sortLists[i].Count % 2 == 0) { median = (sortLists[i][midPoint] + sortLists[i][midPoint + 1]) / 2; } else { median = (sortLists[i][midPoint]); } } catch { } switch (stats.DomainStatType) { case StatTypes.Count: stats.Histogram[i] = sortLists[i].Count; break; case StatTypes.Average: stats.Histogram[i] = average; break; case StatTypes.Median: stats.Histogram[i] = median; break; case StatTypes.Sum: stats.Histogram[i] = sum[i]; break; case StatTypes.Min: stats.Histogram[i] = min[i]; break; case StatTypes.Max: stats.Histogram[i] = max[i]; break; case StatTypes.Ratio: stats.Histogram[i] = sum[i] / denominatorSum[i]; break; default: break; } } } foreach (var j in stats.Histogram) { if (stats.HistogramMax < j) { stats.HistogramMax = j; } } return stats; }
public ColumnStats GetDateHistogram(int column, DateFilter type) { var stats = new ColumnStats(); stats.Computed = true; stats.Buckets = 20; stats.TargetColumn = column; stats.DomainColumn = -1; table.Lock(); stats.Max = double.MinValue; stats.Min = double.MaxValue; switch (type) { case DateFilter.Year: ComputeDateRange(column, -1, out stats.BeginDate, out stats.EndDate); stats.BeginDate = stats.BeginDate.Date; stats.EndDate = stats.EndDate.Date; var ts = stats.EndDate - stats.BeginDate; stats.Buckets = (int)(ts.TotalDays + 1); stats.DomainValues = new string[stats.Buckets]; var now = stats.BeginDate; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i]=now.ToShortDateString(); now = now.AddDays(1); } break; case DateFilter.Month: stats.Buckets = 12; stats.DomainValues = new string[stats.Buckets]; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = UiTools.GetMonthName(i, false); } break; case DateFilter.Day: stats.Buckets = 31; stats.DomainValues = new string[stats.Buckets]; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = (i+1).ToString(); } break; case DateFilter.DayOfWeek: stats.Buckets = 7; stats.DomainValues = new string[stats.Buckets]; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = UiTools.GetDayName(i, false); } break; case DateFilter.DayOfYear: stats.Buckets = 366; stats.DomainValues = new string[stats.Buckets]; for (var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = (i + 1).ToString(); } break; case DateFilter.Hour: stats.Buckets = 24; stats.DomainValues = new string[stats.Buckets]; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = UiTools.GetHourName(i); } break; case DateFilter.Minute: stats.Buckets = 60; stats.DomainValues = new string[stats.Buckets]; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = i.ToString(); } break; case DateFilter.Second: stats.Buckets = 60; stats.DomainValues = new string[stats.Buckets]; for(var i = 0; i < stats.Buckets; i++) { stats.DomainValues[i] = i.ToString(); } break; default: break; } stats.Histogram = new double[stats.Buckets]; stats.BucketWidth = 1; stats.DateFilter = type; // First Pass - Basic statistics.. foreach (var row in table.Rows) { var selected = Filters.Count == 0; var firstFilter = true; foreach (var fgt in Filters) { var filter = fgt.Stats; if (filter.Computed && (selected || firstFilter)) { if (filter.IsSelected(row)) { selected = true; } else { selected = false; } firstFilter = false; } } if (selected) { try { if (column > -1) { var date = ParseDate(row[column]); var bucket = 0; switch (type) { case DateFilter.Year: bucket = (date.Date - stats.BeginDate).Days; break; case DateFilter.Month: bucket = date.Month - 1; break; case DateFilter.Day: bucket = date.Day - 1; break; case DateFilter.DayOfWeek: bucket = (int)date.DayOfWeek; break; case DateFilter.DayOfYear: bucket = date.DayOfYear - 1; break; case DateFilter.Hour: bucket = date.Hour; break; case DateFilter.Minute: bucket = date.Minute; break; case DateFilter.Second: bucket = date.Second; break; default: break; } stats.Count++; stats.Sum += 1; stats.Histogram[bucket]++; } } catch { } } } stats.Selected = new bool[stats.Buckets]; for (var i = 0; i < stats.Buckets; i++) { stats.Selected[i] = false; } foreach (int max in stats.Histogram) { if (stats.HistogramMax < max) { stats.HistogramMax = max; } } table.Unlock(); return stats; }
public Bitmap GetBarChartBitmap(ColumnStats stats) { int Chrome = 25; int height = 150; int count = Math.Min(MaxUnits, stats.Buckets); int border = 10; int colWidth = Math.Min(30, (int)(1000 / count)); int width = count * colWidth; Width = width + 2 * border; Bitmap bmp = new Bitmap(Width, height + border * 2 + 20 + Chrome); Graphics g = Graphics.FromImage(bmp); g.Clear(Color.FromArgb(128, 5, 75, 35)); bool anythingSelected = false; double selectedAmount = 0; double totalAmount = 0; if (stats.Selected != null) { for (int i = 0; i < stats.Buckets; i++) { if (stats.Selected[i]) { anythingSelected = true; selectedAmount += stats.Histogram[i]; } totalAmount += stats.Histogram[i]; } } // Draw title string text = (stats.DomainColumn > -1 ? layer.Table.Header[stats.DomainColumn] + " : " : "" )+ layer.Table.Header[stats.TargetColumn] + " " + stats.DomainStatType.ToString() + ((stats.DomainStatType == StatTypes.Ratio) ? (" to " + layer.Table.Header[stats.DemoninatorColumn]) : ""); title = text; if (anythingSelected && stats.DomainStatType != StatTypes.Ratio) { text += String.Format(" {0:p1} Selected", selectedAmount / totalAmount); } g.DrawString(text, UiTools.StandardGargantuan, Brushes.White, new PointF(border, 0)); string sort = "AZ"; switch (sortType) { case 0: sort = "AZ"; break; case 1: sort = "ZA"; break; case 2: sort = "09"; break; case 3: sort = "90"; break; } if (chartType == ChartTypes.BarChart) { g.DrawString(sort, UiTools.StandardLarge, Brushes.White, new PointF(Width - 25, 0)); } System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat(); drawFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.DirectionVertical; drawFormat.Alignment = StringAlignment.Near; drawFormat.LineAlignment = StringAlignment.Center; SolidBrush brush = new SolidBrush(Color.FromArgb(20, 128, 255)); Brush selectedBrush = Brushes.Yellow; //Brushes.White; Pen pen = new Pen(Color.FromArgb(20, 128, 255)); double logMax = Math.Log(stats.HistogramMax); int end = Math.Min(stats.Buckets, ScrollPosition + MaxUnits); if (stats.Histogram != null) { barHitTest = new Rectangle[stats.Buckets]; for (int i = ScrollPosition; i < end; i++) { int pos = i - ScrollPosition; double val = stats.Histogram[i] / (stats.HistogramMax * 1.05); if (val < 0) { val = 0; } barHitTest[i] = new Rectangle((int)(pos * colWidth) + border, border + Chrome, colWidth, (int)(height)); Rectangle rect = new Rectangle((int)(pos * colWidth) + border, (int)(height - (val * height)) + border + Chrome, colWidth, (int)(val * height)); if (stats.Selected[i]) { g.FillRectangle(selectedBrush,rect); } else { g.FillRectangle(brush, rect); } if (stats.DomainColumn > -1 || (stats.DomainValues != null && stats.DomainValues.Length > pos)) { g.DrawString(stats.DomainValues[i], UiTools.StandardLarge, Brushes.White, new RectangleF((pos * colWidth) + border, border + Chrome, colWidth, height), drawFormat); } } ScrollBarVisible = false; if (MaxUnits < stats.Buckets) { int ScrollAreaWidth = Width - (2 * border); // Scroll bars are needed ScrollBarVisible = true; int scrollWidth = (int)((double)MaxUnits / (double)stats.Buckets * ScrollAreaWidth) +2; int scrollStart = (int)((double)ScrollPosition/ (double)stats.Buckets * ScrollAreaWidth); scrollUnitPixelRatio = (double)ScrollAreaWidth / (double)stats.Buckets; g.DrawLine(Pens.White, new Point(border, height + 22 + Chrome), new Point(border + ScrollAreaWidth, height + 22 + Chrome)); Rectangle rect = new Rectangle(border + scrollStart, height + 15 + Chrome, scrollWidth, 15); g.FillRectangle(brush, rect); } } brush.Dispose(); pen.Dispose(); g.Flush(); g.Dispose(); return bmp; }
public ColumnStats GetSingleColumnHistogram(int column) { var stats = new ColumnStats(); stats.Computed = true; stats.Buckets = 20; stats.TargetColumn = column; stats.DomainColumn = -1; var sortList = new List<double>(); table.Lock(); stats.Max = double.MinValue; stats.Min = double.MaxValue; if (column > -1) { // First Pass - Basic statistics.. foreach (var row in table.Rows) { var selected = Filters.Count == 0; var firstFilter = true; foreach (var fgt in Filters) { var filter = fgt.Stats; if (filter.Computed && (selected || firstFilter)) { if (filter.IsSelected(row)) { selected = true; } else { selected = false; } firstFilter = false; } } if (selected) { try { var sucsess = false; double val = 0; sucsess = double.TryParse(row[column], out val); if (sucsess) { if (val > stats.Max) { stats.Max = val; } if (val < stats.Min) { stats.Min = val; } stats.Count++; stats.Sum += val; sortList.Add(val); } } catch { } } } } table.Unlock(); //2nd pass does not use the table anymore. working from sortList if (stats.Count > 0) { stats.Average = stats.Sum / stats.Count; sortList.Sort(); var midPoint = stats.Count / 2; if (stats.Count % 2 == 0) { stats.Median = (sortList[midPoint] + sortList[midPoint + 1]) / 2; } else { stats.Median = (sortList[midPoint]); } stats.BucketWidth = (stats.Max - stats.Min) / stats.Buckets; stats.Histogram = new double[stats.Buckets]; foreach (var v in sortList) { var bucket = (int)((v - stats.Min) / stats.BucketWidth); stats.Histogram[Math.Min(stats.Buckets - 1, bucket)]++; } stats.Selected = new bool[stats.Buckets]; for (var i = 0; i < stats.Buckets; i++) { stats.Selected[i] = false; } foreach (int max in stats.Histogram) { if (stats.HistogramMax < max) { stats.HistogramMax = max; } } } return stats; }
public static Bitmap GetHistogramBitmap(ColumnStats stats) { Bitmap bmp = new Bitmap(stats.Buckets, 150); Graphics g = Graphics.FromImage(bmp); g.Clear(Color.FromArgb(128, 68, 82, 105)); Pen pen = new Pen(Color.FromArgb(127, 137, 157)); double logMax = Math.Log(stats.HistogramMax); if (stats.Histogram != null) { for (int i = 0; i < stats.Histogram.Length; i++) { double height = Math.Log(stats.Histogram[i]) / logMax; if (height < 0) { height = 0; } g.DrawLine(Pens.White, new System.Drawing.Point(i, 150), new System.Drawing.Point(i, (int)(150 - (height * 150)))); } } pen.Dispose(); g.Flush(); g.Dispose(); return bmp; }