2011-05-25 8 views
6

Sto utilizzando la libreria Chart in .Net 4.0 per creare un istogramma in pila con diverse serie. Il mio obiettivo è un istogramma che mostra il numero cumulativo di azioni (completamenti del rapporto) al giorno in diverse serie (insegnanti). Spesso mancano dati (nessuna attività quel giorno da un particolare insegnante).Il grafico a colonne in pila del grafico Microsoft presenta lacune

ottengo lacune nei bar quando c'è dati mancanti in una serie:

Histogram with gaps in the columns

Il mio codice:

public ActionResult CompletionHistogram(int sid, int width, int height) 
    { 
     Site site = SiteRepository.Get(sid); 
     if (site == null) 
      return new HttpNotFoundResult(); 

     Chart chart = new Chart(); 
     chart.Height = height; 
     chart.Width = width; 
     ChartArea area = chart.ChartAreas.Add("Default"); 

     // Treat each teacher as a series 
     foreach (Teacher t in site.Teachers) 
     { 
      Series series = chart.Series.Add(t.FullName); 
      series.ChartType = SeriesChartType.StackedColumn; 
      series.Name = t.FullName; 

      // Group completions by day (filter out incomplete reports and null timestamps) 
      var groups = t.StudentReports 
       .Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue) 
       .GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date); 

      bool hasPoints = false; 
      foreach (var g in groups) 
      { 
       series.Points.AddXY(g.Key, g.Count()); 
       hasPoints = true; 
      } 

      series.IsValueShownAsLabel = true; 
      series.ToolTip = "#VALX"; 

      if (hasPoints) 
       chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Days, series); 
     } 


     area.AxisX.LabelStyle.Format = "ddd M/d"; 
     return new ChartResult(chart); 
    } 

Come posso rimuovere la

risposta

9

Ho un modo per far funzionare questo
Siamo spiacenti per la risposta lunga, ma ho trovato il modo con cui si tenta di implementare questa risposta interesserà se funziona o meno.

È necessario impostare manualmente il punto su zero mentre si aggiungono punti. Nota: non sono riuscito a farlo funzionare aggiungendo i punti zero dopo il fatto.

Vedere il prossimo ad esempi e schermate risultanti: chart1.Series.Clear(); chart1.Series.Add (new Series()); chart1.Series.Add (new Series()); chart1.Series.Add (new Series()); chart1.Series.Add (new Series());

foreach (Series s in chart1.Series) 
{ 
    s.ChartType = SeriesChartType.StackedColumn; 
} 

//chart1.Series[0].Points.Add(new DataPoint(0, 0)); 
chart1.Series[0].Points.Add(new DataPoint(1, 3)); 
chart1.Series[0].Points.Add(new DataPoint(2, 3)); 
chart1.Series[0].Points.Add(new DataPoint(3, 3)); 

chart1.Series[1].Points.Add(new DataPoint(0, 3)); 
//chart1.Series[1].Points.Add(new DataPoint(1, 0)); 
chart1.Series[1].Points.Add(new DataPoint(2, 3)); 
chart1.Series[1].Points.Add(new DataPoint(3, 3)); 

chart1.Series[2].Points.Add(new DataPoint(0, 3)); 
chart1.Series[2].Points.Add(new DataPoint(1, 3)); 
//chart1.Series[2].Points.Add(new DataPoint(2, 0)); 
chart1.Series[2].Points.Add(new DataPoint(3, 3)); 

chart1.Series[3].Points.Add(new DataPoint(0, 3)); 
chart1.Series[3].Points.Add(new DataPoint(1, 3)); 
chart1.Series[3].Points.Add(new DataPoint(2, 3)); 
//chart1.Series[3].Points.Add(new DataPoint(3, 0)); 

chart1.SaveImage("C:\\Before.png", ChartImageFormat.Png); 

immagine di "before.png": enter image description here

Ora rimuovere i commenti per la serie senza punti dati a un dato valore x:

(Si noti che ho trovato non è così funziona se si aggiungono i punti a un dato valore x per i valori in cui si esegue y = 0 alla fine, ovvero appena prima che salvi l'immagine. L'ordine dei punti nella serie sembra avere importanza per StackedColumn, non ho mai lavorato con questo tipo ad eccezione di indagare su come rispondere a questa domanda in modo che potrebbe essere di conoscenza comune per gli utenti di questo tipo)

chart1.Series.Clear(); 
chart1.Series.Add(new Series()); 
chart1.Series.Add(new Series()); 
chart1.Series.Add(new Series()); 
chart1.Series.Add(new Series()); 

foreach (Series s in chart1.Series) 
{ 
    s.ChartType = SeriesChartType.StackedColumn; 
} 

chart1.Series[0].Points.Add(new DataPoint(0, 0)); 
chart1.Series[0].Points.Add(new DataPoint(1, 3)); 
chart1.Series[0].Points.Add(new DataPoint(2, 3)); 
chart1.Series[0].Points.Add(new DataPoint(3, 3)); 

chart1.Series[1].Points.Add(new DataPoint(0, 3)); 
chart1.Series[1].Points.Add(new DataPoint(1, 0)); 
chart1.Series[1].Points.Add(new DataPoint(2, 3)); 
chart1.Series[1].Points.Add(new DataPoint(3, 3)); 

chart1.Series[2].Points.Add(new DataPoint(0, 3)); 
chart1.Series[2].Points.Add(new DataPoint(1, 3)); 
chart1.Series[2].Points.Add(new DataPoint(2, 0)); 
chart1.Series[2].Points.Add(new DataPoint(3, 3)); 

chart1.Series[3].Points.Add(new DataPoint(0, 3)); 
chart1.Series[3].Points.Add(new DataPoint(1, 3)); 
chart1.Series[3].Points.Add(new DataPoint(2, 3)); 
chart1.Series[3].Points.Add(new DataPoint(3, 0)); 

// If you add the empty points here, it does not seem to work. 
// Empty points are as follows, and are already added above in the 'after' example. 
// chart1.Series[0].Points.Add(new DataPoint(0, 0)); 
// chart1.Series[1].Points.Add(new DataPoint(1, 0)); 
// chart1.Series[2].Points.Add(new DataPoint(2, 0)); 
// chart1.Series[3].Points.Add(new DataPoint(3, 0)); 

chart1.SaveImage("C:\\After.png", ChartImageFormat.Png); 

immagine di "after.png": (? Anche se si può essere in grado di inserirli) enter image description here

Quindi, dato che non è possibile aggiungere gli zero punti dopo il fatto è necessario modificare il codice per qualcosa di simile:

var allPossibleGroups = t.StudentReports; 

var groups = t.StudentReports 
      .Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue) 
      .GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date); 

     bool hasPoints = false; 
     foreach (var g in allPossibleGroups) 
     { 
      if(groups.ContainsKey(g)) 
      { 
       series.Points.AddXY(g.Key, g.Count()); 
       hasPoints = true; 
      } 
      else 
      { 
       series.Points.AddXY(g.Key, 0); 
      } 
     } 

Purtroppo per i blocchi di codice lungo, ma l'esempio era necessario per dimostrare come farlo funzionare, senza cadere nella trappola di aggiungere i punti vuoti (dove y = 0) alla fine, visto che non funzionerà.

Fammi sapere se hai bisogno di ulteriore aiuto.

+0

+1 grazie per i grandi esempi di codice –

5

incontrato lo stesso problema me e voluto condividere la soluzione corretta:

Usa DataManipulator per inserire il mancanti (x, y) valori:

foreach (Series s in chart.Series) 
{ 
    chart.DataManipulator.Sort(PointSortOrder.Ascending, "X", s); 
    chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, s); 
} 
+0

Funziona Perfetto, grazie. Ancora non ho idea del perché questo accada ... – Lambda

+0

Questo per me ha effettivamente fissato le larghezze delle colonne, ma le lacune sono ancora lì. –

0

annodare attraverso serie non funziona per per qualche motivo, ma la prossima soluzione funziona come un fascino:

Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, "Series1, Series2, Series3, Series4")