Berechnung des Durchschnitts pro Datum von Messwerte aus CSV Datei

  • Hallo, wie kann ich folgendes Problemchen lösen:
    Ich habe eine CSV-Datei "H:\daten.csv" die enthällt zwei Spalten: die Erste ist das Datum und die zweite der Messwert. Wie kann ich den Durchschnitt errechnen pro Datum und diese in ein andere Datei schreiben? Ich habe hier ein minimalbeispiel und das funktioniert soweit. Es ist aber nicht die eleganteste Lösung denn das schreiben von der Durchschnitt in der Zieldatei muss zweimal erfolgen (Zeile 16 bis 18 und nochmal in Zeile 24 bis 26). Kann mann das nicht ein bisschen besser machen?

    [autoit]

    $g = FileOpen("H:\daten.csv", 0)
    $line = FileReadLine($g)
    $c = StringSplit($line, ",")
    $dat1 = $c[1]
    $n = 1
    $summe = $c[2]
    While True
    $line = FileReadLine($g)
    If @error Then ExitLoop
    $c = StringSplit($line, ",")
    $dat2 = $c[1]
    If $dat1 = $dat2 Then
    $n = $n + 1
    $summe = $summe + $c[2]
    Else
    $h = FileOpen("H:\durchschnitt.csv", 1)
    FileWriteLine($h, $dat1 & "," & $summe / $n)
    FileClose($h)
    $n = 1
    $summe = $c[2]
    $dat1 = $dat2
    EndIf
    WEnd
    $h = FileOpen("H:\durchschnitt.csv", 1)
    FileWriteLine($h, $dat1 & "," & $summe / $n)
    FileClose($h)
    FileClose($g)

    [/autoit]

    Programmieren ist ein bisschen Wissenschaft und viel Spass! :)

  • Ha ha, ich war vielleicht nicht so deutlich mit mein 'Holzschuhen-Deutsch'... :)
    Also die CSV-Datei mit den Messwerten hat in der ersten Spalten das Datum und in der zweite Spalte der Messwert:


    Nach der Berechnung sollte die Zieldatei so aussehen, für jedes Datum den Durchschnitt (Mittelwert):

    Code
    4-1-2012,757.99
    6-1-2012,564
    7-1-2012,262.54
    8-1-2012,459,97
    9-1-2012,498.71

    Programmieren ist ein bisschen Wissenschaft und viel Spass! :)

  • Prinzipiell müsstest du für jedes vorkommende Datum eine Summe erstellen und einen Zähler wieviele Einträge es zu diesem Datum gibt.
    Das könnte man über ein 2D-Array machen aber eine Schlüssel-Wert Datenstruktur wie ein Dictionary wäre hier wohl die elegantere Wahl.
    In meinem Vorschlag hab ich mal 2 Dictionarys genommen - eines für die Summen - eines für die Anzahl.
    Würde man, wenn das Dictionary gefüllt ist, z.B. in AutoIt $o_nDic("6-1-2012") aufrufen bekäme man als Rückgabe den Wert 2 - die Anzahl der Daten für den 6.1.
    Auf diesem Prinzip beruht dann folgendes Skript:

    Spoiler anzeigen
    [autoit]

    Global $s_FilePath = @ScriptDir & "\daten.csv"
    Global $s_OutFilePath = @ScriptDir & "\durchschnitt.csv"

    [/autoit] [autoit][/autoit] [autoit]

    Global $s_Line, $a_Split, $s_OutFile = ""

    [/autoit] [autoit][/autoit] [autoit]

    Global $h_File = FileOpen($s_FilePath)
    Global $o_SumDic = ObjCreate('Scripting.Dictionary') ; enthält die Summen der Daten
    Global $o_nDic = ObjCreate('Scripting.Dictionary') ; enthält die Anzahl der Werte eines Datums

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Do
    $s_Line = FileReadLine($h_File)
    If @error Then ExitLoop
    $a_Split = StringSplit($s_Line, ",", 2)
    $o_SumDic($a_Split[0]) = $o_SumDic($a_Split[0]) + Number($a_Split[1]) ; Summiere den Wert für das angegebene Datum ( in $a_Split[0]) auf
    $o_nDic($a_Split[0]) = $o_nDic($a_Split[0]) + 1 ; Erhöhe die Anzahl der Werte für das Datum
    Until False
    FileClose($h_File)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    For $k in $o_nDic.Keys ; Gehe alle Schlüssel (hier=die Daten) des Dictionarys durch um überhaupt durch das Dictionary zu iterieren
    $s_OutFile &= $k & "," & Round($o_SumDic($k) / $o_nDic($k),2) & @CRLF ; schreibe erstmal alles in einen String bevor dieser in eine Datei geschrieben wird
    Next

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete($s_OutFilePath)
    FileWrite($s_OutFilePath, StringTrimRight($s_OutFile, 2))

    [/autoit]


    Die Implementierung des Kommas statt des Punktes im vorletzten Wert deiner Beispielausgabedatei müsstest du aber noch selbst einprogrammieren ;)

  • Ha! die Komma war natürlich ein Tippfehler..... sollte nur ein beispiel sein.

    Vielen dank erstmal für die Lösung mit Objektprogrammierung. Damit kenne ich mich nicht aus, ist aber sehr interessant wie mann nich nur mit einer Zahl als Array-index auf einen Wert zugreifen kann sondern auch mit ein String: dass kann sehr nützlich sein.

    Bin jetzt dabei nicht nur den Mittelwert pro Datum zu errechnen sondern auch der Standardabweichung. Dass gestaltet sich ebenfalls schwierig denn die Formel für die Standardabweichung enthällt den Mittelwert (siehe den X mit Horizontalstrich darüber auf http://de.wikipedia.org/wiki/Standarda…nungsgrundlagen ). Meiner Ansicht nach bräuchte mann jetzt zwei Durchgänge über die Messwertedatei: der Erste um für jedes Datum den Mittelwert zu errechnen und der Zweite um den Mittelwert in die berechnung für die Standardabweichung pro Datum zu integrieren. Aber vielleicht geht es auch mit Objektprogrammierung einfacher.

    Programmieren ist ein bisschen Wissenschaft und viel Spass! :)

  • Du kannst dies umgehen wenn du zusätzlich zu der Summe auch die Quadratsumme mit speicherst.
    Dann kannst du aus der Summe, der Quadratsumme und der Anzahl der Messwerte die Standardabweichung berechnen und brauchst damit auch weiterhin nur einen einzigen Durchlauf.
    Ist z.B. >>hier<< beschrieben.