Statistik über Datengruppierung erstellen

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Amelie.

    Statistik über Datengruppierung erstellen

    Hi Zusammen,

    Ich habe ein TypDataTable drin sind je DateTime (Datum mit Uhrzeit) verschiedene Vorfälle.
    Nun möchte ich für ein Chart jeweils die Anzahl der Vorfälle je Stunde haben (z.B. von 7-8, 8-9, 9-10) etc.

    Mein Ansatz ist eine neue Datatable mit Zeit und Anzahl.
    Zum füllen die Ausgangstabelle durch iterieren und zählen.

    Gibt es da was Eleganteres? :rolleyes:

    LG
    Wolfy

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Moin moin

    Mir fällt dazu "LINQ" ein.
    Mit LINQ kannst du die Anzahl der Vorfälle pro Stunde berechnen und in eine neue DataTable einfließen lassen.

    Daten nach den Stunden des DateTime gruppieren
    Dann innerhalb der Gruppe die Anzahl ermitteln
    Dann in das neue DataTable schreiben
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Wolfy schrieb:

    Da die Anzahl der Datensätze nicht riesig ist, geht es ja auch so.
    Was LINQ angeht wäre eine große Datenmenge sogar von Nachteil.
    LINQ hat eine nicht sonderlich schöne Performance (vor NET9). Ab NET9 hat sich das zum Glück geändert und LINQ ist in den meisten Fällen kaum schlechter als eine handgetippte Schleife.
    Am Ende ist LINQ nur eine Schönschreibweise für Schleifen. Also so wie du sagtest "eleganter" nicht performanter.
    @Haudruferzappeltnoch
    :thumbsup:
    Super Antwort. Danke

    Nun noch eine Frage:
    Wie gesagt Daten kommen aus Datatable:
    Bsp: Ich möchte ein Chart mit Spline (o.ä.).

    X-Achse die Tage
    Y-Achse Anzahl der Besucher
    Das Spline soll die Anzahl der Besucher für die Tage 0 bis 7 (Sonntag bis Samstag) zeigen. Für z.B. KW42
    Nun möchte ich für direkten Vergleich gleichzeitig die KW43 und KW44 auch als Spline angezeigt haben.
    Wie bei EDR im ChartTester.

    Aber so muß ich für jede KW eine eigene Spalte machen. D.h. Wenn ich das ganze Jahr machen wollte 52 Spalten (Ok das ganze Jahr währe nicht mehr wirklich Sinnvoll).
    Da ich vor der Statistik-Datatable die Ergebnisdaten in ein Array schreibe und dann erst aus diesem in die Datatable schreibe ... sollte ich mich doch wohl jetzt schon mit LINQ befassen.
    Oder kann man das Chart in diesem Fall eleganter füttern?
    Ich habe verschiedene Varianten (8) probiert, aber es kommt nur Müll raus.
    Ggf. Habe ich auch einen Denkfehler oder sogar einen Knoten im Hirn.

    Bin gespannt.
    Also wie gesagt LINQ ist zum Codesparen. Die Logik muss man schon erstmal auf die Kette kriegen. Egal ob eigene Schleife oder Linq

    Ich denke ich kenne EDRs Charttester nicht. Ich kann mir noch nicht viel von dem vorstellen was du haben möchtest.
    Zeige doch mal eine Variante. Zeige auch einmal die Ausgangstabelle. Da du ja mit typisierten DataTables arbeitest, wäre ein Bild vom DataSet schon sehr hilfreich.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Wie gesagt Datatable wir entsprechend den Anforderungen erstellt.
    Zum Bild:
    Bei mir X-Achse = Tage, Y-Achse = Besuche, Splines = die KW´s.
    Muß ich nun für die KW´s eigene Spalten in der Datatable anlegen?

    LG
    Wolfy
    Bilder
    • chart-bsp.png

      35,29 kB, 622×523, 134 mal angesehen
    Das weiß ich noch nicht.

    Ich verstehe nun weniger als vorher.
    Erstmal passt das Bild nicht zu deinen Beschreibungen, die Splines heißen Logins und Registers, nicht KW11 und KW12.
    Und mit KWs machts auch wenig Sinn weil die x-Achse das Datum ist. Die liegen dann alle an unterschiedlichen Stellen im Diagramm, ist das gewollt, bzw. warum dann nicht gleich einen durchgehenden Spline?

    Hast du sowas oder was bezeichnest du als typDataTable?
    Hi.
    OK hast mich falsch verstanden. Das Bild war von EDR's ChartTester.
    Latürnich eine Datatable aber mit 53 Spalten 52 für jede Woche plus 1 für Tage

    ich habe es im Moment wie folgt:
    Daten aus- einlesen

    VB.NET-Quellcode

    1. 'Schleife zum Einlesen in diverse Array's
    2. For Each row As DataRowView In DataTable2BindingSource
    3. TempDate = DirectCast(row(1), Date)
    4. TempHour = CInt(TempDate.Hour)
    5. tempDay = TempDate.DayOfWeek
    6. tempMonth = TempDate.Month
    7. tempWeek = DatePart(DateInterval.WeekOfYear, TempDate, FirstDayOfWeek.Monday, FirstWeekOfYear.FirstFourDays)
    8. besH(TempHour) = besH(TempHour) + 1
    9. besT(tempDay) = besT(tempDay) + 1
    10. besW(tempWeek) = besW(tempWeek) + 1
    11. besM(tempMonth) = besM(tempMonth) + 1
    12. besWT(tempWeek, tempDay) = besWT(tempWeek, tempDay) + 1
    13. besTW(tempDay, tempWeek) = besTW(tempDay, tempWeek) + 1
    14. besTKW(tempDay, tempWeek) = besTKW(tempDay, tempWeek) + 1
    15. Next
    16. 'Füllen der Datatable mit 53 Spalten
    17. Dim rw As DataRow
    18. For i = 0 To besTKW.GetUpperBound(0)
    19. For w = 0 To besTKW.GetUpperBound(1)
    20. If w = 0 Then rw = dtSKWT.NewRow
    21. rw.Item(w) = besTKW(i, w)
    22. 'dtSKWT.Rows.Add(i, w, besTW(i, w))
    23. Next
    24. dtSKWT.Rows.Add(rw)
    25. Next


    Und Chart erzeugen:

    VB.NET-Quellcode

    1. ChartZeitBesuche.DataSource = KWTagBindingSource
    2. ChartZeitBesuche.ChartAreas(0).AxisX.Maximum = 7
    3. ChartZeitBesuche.ChartAreas(0).AxisX.Minimum = 1
    4. ChartZeitBesuche.ChartAreas.Item(0).AxisX.Title = "Tag"
    5. ChartZeitBesuche.Series.Clear()
    6. For i = 40 To 50
    7. ChartZeitBesuche.Series.Add("KW" & i.ToString)
    8. ChartZeitBesuche.Series("KW" & i.ToString).YValueMembers = "KW" & i.ToString
    9. ChartZeitBesuche.Series("KW" & i.ToString).XValueMember = "Tag"
    10. ChartZeitBesuche.Series("KW" & i.ToString).ChartType = SeriesChartType.Spline
    11. ChartZeitBesuche.Series("KW" & i.ToString).MarkerStyle = MarkerStyle.Diamond
    12. Next


    Zumindest funktioniert es nun.
    Siehe Bild

    jetzt muß ich nur noch an der X-Achse Montag, Dienstag etc. stehen haben statt 1, 2, 3

    langsam wirds

    LG
    Wolfy
    Bilder
    • Tag-KW.png

      144,08 kB, 937×707, 128 mal angesehen
    Hm also das sieht nicht nach einer typisierten DataTable aus. Zumindest benutzt du sie nicht.

    Aber du könntest ohne die KW-Spalten auskommen, wenn du darauf verzichten magst auf das Chart zu binden. Dadurch muss man dann mehr im Code statt im Designer einstellen, aber das tust du ja jetzt schon.
    Ich denke, so könnte das aussehen mit den richtigen Voraussetzungen (PseudoCode):

    VB.NET-Quellcode

    1. Dim KWs = DS1.Rohtabelle.GroupBy(Function(z) GetKW(z.tempDate)) _
    2. .Select(Function(g) (ID:=g.Key, Tage:=g.GroupBy(Function(x) x.tempDate.DayOfWeek).Select(Function(gg) (ID:=gg.Key, Besuche:=gg.Count)).ToArray))
    3. For Each KW In KWs
    4. Dim curSeries = Chart1.Series.Add($"KW{KW.ID}")
    5. For Each _tag In KW.Tage
    6. curSeries.Points.AddXY(_tag.ID, _tag.Besuche)
    7. Next
    8. Next

    Moin moin

    @Wolfy

    ​Datatable aber mit 53 Spalten 52 für jede Woche plus 1 für Tage

    Für jede KW eine Spalte? Warum nicht die KW als Integer ? Dann hättest du in einen DT eine Row "KW" und eine Row "Tage".....

    ​X-Achse Montag, Dienstag etc. stehen haben statt 1, 2, 3

    Entwerder aus einem Enum oder je nachdem wie die Daten in deinen DT sind mit "Format" ....

    Vielleicht wäre es Hilfreich, wenn du mal deine ganzen DT zeigst??
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @'Haudruferzappeltnoch
    Danke.
    Das is mal ein Ansatz den ich demnächst ausprobieren werde. :thumbsup:
    Doch Datatable hat nur Integer-Spalten.

    @'Amelie
    vb-paradise.de/index.php/PostA…7/?quoteMessageID=1192054Für jede KW eine Spalte? Warum nicht die KW als Integer ? Dann hättest du in einen DT eine Row "KW" und eine Row "Tage".....vb-paradise.de/index.php/PostA…7/?quoteMessageID=1192054

    Ja da ich sonst die Darstellung nicht hinbekomme.
    Da ist wohl der Knoten bei mir.


    Bin gespannt

    Bilder
    • Screenshot 2024-11-20 155030.png

      5,24 kB, 170×298, 124 mal angesehen
    @Wolfy

    ich meinte eigentlich alle deine DT, damit man mal einen Überblick bekommt wie da was bei dir zusammenspielt.

    Habe mir mal ein paar Gedanken gemacht, über das was ich so von der ersten Fragestellung verstanden habe.

    XML-Quellcode

    1. 1.) DT ==> KW und Jahr (beides als Integer)
    2. 2.) DT ==> KW (fk) Tag (beides als Integer)
    3. 3.) DT ==> KW (fk) Tag (fk) Besucher (beides als Integer)
    4. 4.) DT ==> ....

    So könnte man z.B. das Datum, Besucherzahlen usw leicht herrausfiltern und im Chart anzeigen lassen....
    Für Tages;- Monats-Namen würde ich je ein Enum anlegen... Hätte den Vorteil der gleichen Typen ...

    Sind nur meine Ideen :D
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    OK.
    Danke.
    Mal der Reihe nach:

    Möchte gerne das Thema mit der Enumeration (Wochentage für die Zahlen 0 bis 6)
    Enum Habe ich.
    Wie weise ich die Umwandlung der Zahlen für die X-Achse im Chart an.
    Es wird ja mit Zahlen von 0-6 gefüttert?

    Ich stehe auf der Leitung.


    @Amelie
    Das Problem bei diesen Sammeltabellen, ist meiner Meinung nach, dass man dort Jahre, KWs, Tage "anlegen" muss.
    Das gibt dann so schöne Bugs, wie dass nach X Jahren Betrieb irgendwas plötzlich nicht mehr funktioniert, weil noch keiner 2032 in so einer Tabelle eingepflegt hat.

    Das sind alles Werte, die aus einem Datum berechnet werden können und sollten entsprechend immer verfügbar sein.

    @Wolfy
    Die X-Achse sollte mit dem DayOfWeek Enum gefüttert werden. Während DayOfWeek.Monday 1 ist, ist DayOfWeek.Monday.ToString Monday.
    Es gibt da so Spielereien im Chart, dass man über curSeries.Points(i).AxisLabel = _tag.ID.ToString
    und curSeries.AxisLabel = "#LABEL" das hinkriegen kann.
    Aber es gibt bestimmt noch andere Wege, zumal ich das nicht sonderlich schön finde.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    schon eine einfache Access-Datenbank in betracht gezogen ? diese kann Pivottabellen erstellen

    hier ein simples Bsp. für verschiedene KFZ und die Erzeugung von verschiedenen Pivottabellen
    -Jahre-Monat
    -Jahre-Monat-Tage
    -Jahre-KW

    ich persönlich finde die Daten sind so besser lesbar als Charts

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Data.OleDb
    3. Public Class Form2
    4. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    5. Dim FrozenColumsCount As Integer = 3
    6. ''für Jahre Monate
    7. Dim sql As String = <sql>
    8. TRANSFORM Sum(tbl_Tanken.GetankteLiter) AS SummevonGetankteLiter
    9. SELECT Format([TankDatum],"yyyy") AS [in Jahr],
    10. tbl_Tanken.KFZ, Sum(tbl_Tanken.GetankteLiter) AS Gesamt
    11. FROM tbl_Tanken
    12. GROUP BY Format([TankDatum],"yyyy"), tbl_Tanken.KFZ
    13. PIVOT Format([TankDatum],"mmm") In ("Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez");
    14. </sql>.Value
    15. ''für Jahre-Monate-Tage
    16. 'Dim sql As String = <sql>
    17. ' TRANSFORM Sum(tbl_Tanken.GetankteLiter) AS SummevonGetankteLiter
    18. ' SELECT Format([TankDatum],"yyyy") AS [in Jahr], Format([TankDatum],"mm") AS [in Monat], Sum(tbl_Tanken.GetankteLiter) AS Gesamt, tbl_Tanken.KFZ
    19. ' FROM tbl_Tanken
    20. ' GROUP BY Format([TankDatum],"yyyy"), Format([TankDatum],"mm"), tbl_Tanken.KFZ
    21. ' ORDER BY Format([TankDatum],"mm")
    22. 'PIVOT Format([TankDatum],"dd") In ("01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31");
    23. '</sql>.Value
    24. ''für Jahr - Kalenderwoche
    25. 'Dim sql As String = <Sql>
    26. ' TRANSFORM Sum(tbl_Tanken.GetankteLiter) AS SummevonGetankteLiter
    27. ' SELECT Format([TankDatum],"yyyy") AS [in Jahr], tbl_Tanken.KFZ, Sum(tbl_Tanken.GetankteLiter) AS Gesamt
    28. ' FROM tbl_Tanken
    29. ' WHERE (Format([TankDatum],"yyyy"))=2020
    30. ' GROUP BY Format([TankDatum],"yyyy"), tbl_Tanken.KFZ
    31. ' PIVOT Format([TankDatum],"ww")In ("1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36");
    32. '</Sql>.Value
    33. Dim dt As DataTable = GetData(sql)
    34. DataGridView1.DataSource = dt
    35. With DataGridView1
    36. For i As Integer = 3 To .Columns.Count - 1
    37. .Columns(i).Width = 50
    38. .Columns(i).DefaultCellStyle.Format = "c"
    39. .Columns(2).DefaultCellStyle.Format = "c"
    40. Next
    41. End With
    42. 'Freeze
    43. For i As Integer = 0 To FrozenColumsCount - 1
    44. DataGridView1.Columns(i).Frozen = True
    45. Next
    46. End Sub
    47. Private Shared Function GetData(ByVal query As String) As DataTable
    48. Dim constr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\Adressen.mdb"
    49. Using con As OleDbConnection = New OleDbConnection(constr)
    50. Using sda As OleDbDataAdapter = New OleDbDataAdapter(query, con)
    51. Dim dt As DataTable = New DataTable()
    52. sda.Fill(dt)
    53. Return dt
    54. End Using
    55. End Using
    56. End Function
    57. End Class


    hier noch ein paar Bilder:
    Tabelle Tanken


    Pivot Monat

    Hey,

    @Kasi
    Die Überlegung habe ich tatsächlich noch nicht angestellt.
    Es ist eine gute Alternative und einfacher. Dafür brauche ich auch kein Access. :thumbsup:

    @Haudruferzappeltnoch
    Deinem Ansatz wollte ich ja umsetzen. Aber wie erscheint statt der 1 der Montag und für 2 der Dienstag ...?
    Ich habe den DayofWeek Wert (Integer) in der Datatable Spalte Tag.
    Die Spalte Tag ist aber auch schon dem XValueMember zugeordnet

    VB.NET-Quellcode

    1. ​ChartZeitBesuche.Series("KW" & i.ToString).XValueMember = "Tag"

    Was muss ich noch hinbiegen?
    Mit Binding weiß ich gerade keinen automatischen Ansatz. So oft hab ich dann auch noch nicht mit Charts gearbeitet.
    Aber theoretisch kannst du eine TagName Spalte machen und die hernehmen, wobei das wär ja n String, da weiß ich auch nicht wie sich das verhält, aber probieren kannst es.

    Mein Vorschlag aus Post 15 bezog sich auf den Ansatz aus Post 10, da is nix mehr mit Data- und ValueMembern,
    und wenn man da eh schon in den Points gräbt kann man gleich Customlabels vergeben.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    @Wolfy

    Moin moin

    Ich habe mal ein Chart mit den Wochentagen gebaut. Hoffe das es das abbildet was du meinst.
    Wenn du das Chart mit "Montag" beginnen möchtest, setze im Enum den "Montag" am Anfang. ;)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Enum Wochentage
    2. Sonntag = 1
    3. Montag = 2
    4. Dienstag = 3
    5. Mittwoch = 4
    6. Donnerstag = 5
    7. Freitag = 6
    8. Samstag = 7
    9. End Enum


    VB.NET-Quellcode

    1. Public Class Form1
    2. Public Sub New()
    3. InitializeComponent()
    4. End Sub
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. InitializeChart()
    7. PseudoDaten()
    8. End Sub
    9. Private Sub InitializeChart()
    10. ' Chart-Einstellungen
    11. Chart1.Series.Clear()
    12. Chart1.ChartAreas.Clear()
    13. Chart1.Titles.Clear()
    14. Dim chartArea As New ChartArea("MainArea")
    15. chartArea.AxisX.Title = "Wochentage"
    16. chartArea.AxisY.Title = "Kundenanzahl"
    17. chartArea.AxisX.Interval = 1
    18. chartArea.AxisY.Interval = 10 ' Einteilung kann man ggf anpassen
    19. Chart1.ChartAreas.Add(chartArea)
    20. Chart1.Titles.Add("Kunden pro Wochentag und Kalenderwoche")
    21. End Sub
    22. Private Sub PseudoDaten()
    23. ' Enum-Wochentage
    24. Dim wochentage = [Enum].GetValues(GetType(Wochentage))
    25. Dim random As New Random()
    26. ' Daten für 3 Serien (Kalenderwochen)
    27. For i As Integer = 1 To 3
    28. Dim kw As Integer = random.Next(1, 53) ' Zufällige Kalenderwoche zwischen 1 und 52
    29. Dim seriesName As String = $"KW {kw}"
    30. Dim series As New Series(seriesName)
    31. series.ChartType = SeriesChartType.Spline
    32. series.MarkerStyle = MarkerStyle.Circle
    33. series.ChartArea = "MainArea"
    34. ' Pseudodaten für jeden Wochentag in dieser KW
    35. For Each tag As Wochentage In wochentage
    36. Dim kundenanzahl = random.Next(0, 90) ' Zufällige Kundenanzahl zwischen 0 und 90
    37. series.Points.AddXY(tag.ToString(), kundenanzahl)
    38. Next
    39. ' Serie zur Chart hinzufügen
    40. Chart1.Series.Add(series)
    41. Next
    42. End Sub
    43. End Class

    Bilder
    • Chart.jpg

      165,81 kB, 768×450, 122 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh: