Statistische Auswertung Pakete

Hallo zusammen,
bin noch ziemlich unerfahren was das Programmieren angeht und deshalb zur Zeit mit meiner Problemstellung etwas überfordert.

Es geht um eine statistische Auswertung der folgenden CSV Datei:
https://onedrive.live.com/redir?resid=52BDC287A4085523!2188&authkey=!AAB6xgNt9aLb9KQ&ithint=file%2Ctxt
Die Datei ist 2,26mb groß, weshalb ich sie nicht hier direkt hochladen konnte. Ich hoffe das stört nicht.

Jede Zeile repräsentiert ein “Paket”.
Ich möchte nun gerne wissen, welche durchschnittliche, maximale und** minimale Länge**, Höhe, Breite und Volumen meine Pakete pro Entlademodul (hier ist jetzt nur EM06 als Entlademodul. In anderen Dateien kommen aber noch andere Module wie z.B. EM01 vor) pro Stunde bzw. **pro Schicht **und in 100mm Schritten haben:
Also z.B. die durchschnittliche Höhe der Pakete mit Höhe 100-200mm zwischen 6 - 7 Uhr.

(Hinweis: Eine CSV Datei besteht aus 2 Schichten. Einmal am Vortag (hier: 19.8.) von 12:00 bis 0:00 und dann der Morgen des Tages von 0:00 bis 08:00 Uhr (hier: 20.8.)

Die Ergebnisse sollen am besten in eine CSV Datei ausgegeben werden, sodass ich diese in Excel importieren und grafisch darstellen kann.

Hinweis: Ich habe mehrere dutzend von diesen Dateien für verschiedene Tage, weshalb ich das ganze in eine Schleife einbauen werde, um dann als Output eine CSV Datei zu erhalten.

Würde mich über jede Hilfe freuen,

Vielen Dank im Voraus,
David

Wieso machst Du das nicht gleich in Excel, wenn das sowieso das Zielformat ist?

bye
TT

[QUOTE=Dathor]Also z.B. die durchschnittliche Höhe der Pakete mit Höhe 100-200mm zwischen 6 - 7 Uhr.
[/QUOTE]

Nur zwischen 6 und 7 Uhr? 6:59:59 Uhr inbegriffen, 7:00 Uhr inbegriffen? Stehen in der Tabelle nur zwischen 6 und 7 Uhr? Müssen Tage berücksichtigt werden? Muss die Uhrzeit geparst werden?

Edit: Super, ich suche alle Menüpunkte rechts davon ab, und ‘Herunterladen’ ist der erste Menüpunkt.

mal eine Verwarnung - wenn du nichts zum Thema fachliches beizutragen hast, lass dieses Gebrabbel. Nächstes mal werde ich auch solche Posts löschen.

aus der 2,26 MB-Datei könntest du 10 oder 100 Test-Zeilen oder was auch immer (habe sie nicht angeschaut) auswählen, so dass ein paar Probleme gut damit abgebildet sind,
mit denen eine eigene Datei, sicher erstellbar,
dann wäre die Frage mit einer 10 KB Datei genauso lösbar, und du hättest Initiative gezeigt (oder noch edler verschwiegen :wink: ) und eine Reihe Probleme/ Komplexität vermieden


als nächstes ist zu sagen dass CSV-Einlesen (+ später evtl. wieder schreiben) ein Grundlagen-Thema ist, nahezu komplett unabhängig vom Rest, vom Statistik-Thema,
zu CSV könntest du in Suchmaschinen bestens zig Methoden finden, das für sich üben, evtl. für sich hier dazu fragen,

direkt dazu gehört freilich eine gewisse Modellierung, irgendeine Klasse X, vielleicht Paket, mit Datenfeldern Länge, Höhe, Breite als int oder double usw., ans CSV-Format angelehnt,
so eine Klasse ist nun auch ziemlich das einfachste, was man programmieren kann,
evtl. auch nachzufragen aber besser jedenfalls nicht mit anderen Themen vermischen


idealerweise das alles ausgeklammert als nächstes ein reines Java-Programm mit Test-Daten direkt hineinprogrammiert,
Liste von Paket-Objekten etwa, 10-100 mit Länge 25 usw. in main-Methode definiert, bereit zur Auswertung,

dann kann man mit der eigentlichen Frage beginnen, zu der ich nach so viel jetzt schon offenen Punkten vorerst nichts sage

wenn du nur die Frage stellst und nichts an eigenen Code/ Ideen beiträgst, sieht das übrigens generell schlecht aus, habe das Thema nach ‚Hausaufgaben‘ verschoben, als erste Wertung :wink:

Nö, bin ich nicht mit einverstanden, aber ich melde deinen Beitrag mal nicht.

Ich erstelle ihm gerade die statistische Auswertung, falls du es nicht gemerkt habn solltest.

Edit: Als Durchschnittswerte hab ich da raus:

Avr Hei: 144.26 mm
Avr Wid: 266.47 mm
Avr Len: 388.81 mm
Avr Vol: 22293.20 cm^3

Dabei ist mir aufgefallen, das manche Werte für h, w, l, v 0 oder 1 mm sind, was ja theoretisch nicht sein kann, Volumen 0.

Zunächst einmal ein großes Danke für die vielen, schnellen Rückmeldungen.

[QUOTE=Timothy_Truckle;125936]Wieso machst Du das nicht gleich in Excel, wenn das sowieso das Zielformat ist?

bye
TT[/QUOTE]

Ich habe z.Z. einen Zeitraum von zwei Monaten, wobei pro Tag und pro Entlademodul (zur Zeit 3 Entlademodule) eine CSV-Datei mit im Schnitt 6mb exisitiert (Die Variante, die ich zur Verfügung gestellt habe, ist schon gekürzt). Also macht das ungefähr 3023 = 180 CSV Dateien. Eine dieser Dateien hat ca. 60.000 Zeilen. Ich dachte, dass das nicht nur sehr lange dauert, diese ganzen Dateien zu importieren, sondern auch dass das Zeilenlimit von Excel damit überschritten wird.

*** Edit ***

Das mit den Testzeilen werde ich das nächste mal machen, ich dachte mir nur, dass das hochladen deutlich schneller geht als aus 60000 Zeilen hinreichend viele Stichproben zu sammeln :wink:


Das CSV-Datei Lesen und Schreiben via BufferedReader und -Writer kriege ich hin.

Ich hätte erwähnen müssen, dass ich gerade an dem Punkt des Programmierens bin, wo mein Reader die CSV Datei quasi Zeile für Zeile durchgeht. Eine Klasse „Paket“ habe ich bisher noch nicht erstellt, dachte das wäre nicht notwendig, wenn ich die CSV Datei Zeile für Zeile durchgehe und die Informationen verarbeite.


Mein Hauptproblem (auch das hätte ich noch erwähnen müssen) ist quasi die Dichte der Auswertung, also, dass alles pro Stunde und noch zusätzlich je 100mm sein soll. Um eine gute und effiziente Herangehensweise an so ein Problem zu haben, kenne ich mich mit der Programmierung und den Möglichkeiten, die Java bietet, leider zu wenig aus.

[QUOTE=CyborgBeta]Nö, bin ich nicht mit einverstanden, aber ich melde deinen Beitrag mal nicht.

Ich erstelle ihm gerade die statistische Auswertung, falls du es nicht gemerkt habn solltest.

Edit: Als Durchschnittswerte hab ich da raus:

Avr Hei: 144.26 mm
Avr Wid: 266.47 mm
Avr Len: 388.81 mm
Avr Vol: 22293.20 cm^3

Dabei ist mir aufgefallen, das manche Werte für h, w, l, v 0 oder 1 mm sind, was ja theoretisch nicht sein kann, Volumen 0.[/QUOTE]

Vielen Dank für deine Bemühungen, ich stehe gerade an dem Punkt, wo mein Programm quasi Zeile für Zeile das CSV Dokument durchgeht. Ich hätte jetzt vermutlich mit ewig vielen Variablen und if Abfragen gearbeitet, aber ich glaube das wäre viel zu kompliziert und auch nicht wirklich zielführend.

Wenn manche Werte 0 sind, kann das Paket übersprungen werden. Es müsste dann nur einen Zähler geben, der mir pro Schicht bzw pro Stunde angibt, wieviele Pakete keine Dimensionsdaten hatten.

Hier ist der <()>< , wenn man so möchte:

        new HWLVPaket(true),
        new HWLVPaket(false),
        new HWLVPaket(true),
        new HWLVPaket(false),
        new HWLVPaket(true),
        new HWLVPaket(false),
        new HWLVPaket(true),
        new HWLVPaket(false)
    };

class HWLVPaket {

    boolean mit0;
    int anz = 0;
    int sum = 0;
    int min = Integer.MAX_VALUE;
    int max = Integer.MIN_VALUE;

    public HWLVPaket(boolean mit0) {
        this.mit0 = mit0;
    }

    public void add(int i) {
        if (mit0 || i >= 1) {
            anz++;
            sum += i;
            min = i < min ? i : min;
            max = i > max ? i : max;
        }
    }

    public double getAvr() {
        return sum / (double) anz;
    }
}```

wegen **pro Stunde** und **je 100 mm** würde ich noch eine Art Validator/Verifier 'einbauen'.

Weite, Länge undOder Volumen kannDarf 0 sein?

Generell wird es einfacher (jedenfalls den Überblick zu behalten und später mal wieder daran zu arbeiten) wenn man sein Programm in verschiedene Klassen/Methoden aufteilt.
So ist es im späteren Verständnis einfacher, man hat eine Klasse Paket mit den werden

public class Paket{
   private int hoehe;
   private int breite;
   //...
   public void Paket(int hoehe, int breite){
      this.hoehe=hoehe;
      this.breite=breite;
   }

   public int getHohe(){
      return hoehe;
   }
   //...
}

wenn man nun beim Einlesen jede Zeile in ein objekt der Klasse packt und diese in einer Liste speichert, kann man diese später dann einfach verwenden.
Theoretisch könntest du auch verschiedene Listen anlegen, die schon deine verschiedenen Bereiche abdecken.
So z.b. eine Liste für Pakete mit den maßen 100mm-200mm und in diese nur die Pakete legen, die in diese Bereiche passen.
Anschließend könntest du nun über diese Pakete in einer Schleife itterieren und dort den Mittelwert berechnen.
Die generelle Formel nehme ich an dafür kennst du

PS @CyborgBeta nein das konnte man nicht aus deinem Kommentar lesen, das du an dem Problem arbeitest. Auch hast du dem TO keinen Tip gegeben wie man daran arbeitet oder den Code offengelegt. Und das er dich für alle Auswertungen immer anruft, ist glaube ich auch eine schlechte Lösung (oder ein Business-case)

@Dathor

Postings neuer User müssen manchmal erst freigeschaltet werden, Spam-Schutz, lieber nicht öfters versuchen,

Danke an fast jedes vorherige Posting dran ist nebenbei angemerkt weder erwartet noch hilfreich sondern entwertet dieses kleine System :wink:


wenn CSV-Einlesen klappt, dann brauchst du auch nicht so sehr Kleindatei bemühen, lieber gleich zum Code gehen, etwa als Ausgang sowas:

public class Test2 {
    public static void main(String args[])  {
        List<Data> list = new ArrayList<>();
        list.add(new Data(4, 5));
        list.add(new Data(4, 6));
        list.add(new Data(4, 7));
        list.add(new Data(5, 9));
        list.add(new Data(5, 3));
        
    }

    static class Data  {
        int x;
        int y;

        public Data(int x, int y)   {
            this.x = x;
            this.y = y;
        }
    }
}

und dann mit der Liste der Daten irgendwas anfangen

es gibt vielleicht irgendwo auf der Welt professionelle Tools, wo du deine Daten nur mit Parametern eingeben musst,
nach Attributen a, b, c unterscheiden, d summieren, f Durchschnitt usw.,

aber wenn du es einfach halten willst, dann einfach drauflos analysieren, eine von vielen Varianten:

zunächst könntest du für alle Elemente der Liste ohne Unterscheidung die durchschnittliche Höhe und anderes bestimmen, Formeln sicher klar, aufsummieren und teilen,
das idealerweise in eine Untermethode zur späteren Verwendung,


zweiter Schritt ist die Unterscheidung,
nimm jeden Eintrag, schau dir die Merkmale wie Modul an usw. und sortiere das Element in eine entsprechende Teilliste ein, am Ende die Analyse auf die Teillisten

dafür braucht es eine Struktur der Teillisten, einfache Sache ist dabei eine Map<String,Liste>
baue für jeden Eintrag einen String-Key zusammen, mit Modul & Co. zusammengefügt, zum String die Liste aus der Map holen, evtl. anlegen, darin den Eintrag sammeln

leicht sind direkte Unterscheidungsmerkmale wie Modul,
schwieriger die die noch etwas umzuformen sind:
eine Uhrzeit wie 6:23 oder 6:24 muss in ein gemeinsames Merkmal wie „6-7 Uhr“ umgewandelt werden, 123mm in „100-200mm“,
in Zahlen und Uhrzeit parsen, Stunde bestimmen bzw. Modulo 100 rechnen usw.


wenn am Ende die Listen aus der Map einzeln ausgewertet hat man den String-Key dazu um auch eine Aussage zu haben, welche Daten denn da jeweils dran sind,
falls der so geformt ist dass er direkt wieder ausgegeben werden kann, evtl. beim Zusammenbau mit ; dazwischen für CSV-Format, kann man den nehmen,

wenn nicht ausreichend, dann eben kein String-Key in der Map sondern irgendein höheres Objekt mit entsprechenden Feldern, evtl. gar ein Data/ Paket-Objekt selber mit nur den entsprechenden Feldern gefüllt, equals und hashCode implementieren falls dir das was sagt,

viel auf einmal, muss nicht alles verstanden sein

*** Edit ***

es geht freilich auch ohne Datenobjekte, richtig,
sie müssen auch nicht in Teillisten sondern können direkt einmalig verarbeitet werden,

Unterscheidungsfrage wie bisher,
dann dort wo es zur Sache geht gleich aufsummieren/ Min/ Max bestimmen wie in Posting #9 von CyborgBeta durchaus zu sehen…

[QUOTE=Unregistered]
PS @CyborgBeta nein das konnte man nicht aus deinem Kommentar lesen, das du an dem Problem arbeitest. Auch hast du dem TO keinen Tip gegeben wie man daran arbeitet oder den Code offengelegt. Und das er dich für alle Auswertungen immer anruft, ist glaube ich auch eine schlechte Lösung (oder ein Business-case)[/QUOTE]

Hab ich ja jetzt gepostet. Wegen Tag, Uhrzeit und 100 mm bin ich aber inzwischen bei einem if-else-if-Gerüst angekommen, was sicher nicht richtig ist.

Evtl. kann etwas über die Reihenfolge in der Liste/Tabelle gemacht werden.

alternativ wäre über einen Datenbank nachzudenken, wo man solche Auswertungen auch geschenkt bekommt.

bye
TT

Mit DB Management habe ich mich bisher noch nicht beschäftigt.
Kannst du mir dafür eine Datenbank Programm empfehlen? MS Access steht mir aus irgendwelchen lizensrechtlichen Gründen leider nicht zur Verfügung. Auf dem Rechner sind keine Administratorenrechte vorhanden.

Das mit der DB habe ich mir auch schon gedacht, dass das doch eine simple alternative ist, und schließlich für das bearbeiten von größeren Datenmengen auch recht vorteilhaft.
Es gibt sogar im i-net Tools die eine Konvertierung von csv zu SQL ermöglichen wie z.b. das hier CSV zu MySQL Konverter vielleicht hilft Dir das auch ein Stückchen weiter in deiner Überlegung.
Dann müsstest du dir nur noch die passenden SQL Statements zusammen bauen :wink:

*** Edit ***

Als einfache Simple DB kannst du dir mal https://www.mysql.de/ anschauen und würde ich glaube ich generell auch MS Access vorziehen.
Ansonsten gibt es verschiedenste DB von Kostenlos bis Kostenpflichtig von MS bis zu Oracle und IBM

Welche sich etwa über 10 Zeilen erstrecken dürften.

Aber besser, als sortieren teilen und if-else-if-‚Monstrum‘.

@SlaterB

Danke für die ausführliche Antwort. Ich werde mal versuchen, mich an deiner „Anleitung“ entlang zu hangeln. Fragen werden sich dabei dann vermutlich genug ergeben :smiley:
@CyborgBeta

Ich hoffe ich habe deine offenen Fragen soweit klären können.
Danke für den Code den du mir bislang gepostet hast. Werde mal versuchen daraus schlau zu werden, aber auf den ersten Blick hatte ich da jetzt noch nicht wirklich so den Durchblick.

@Unregistered
Werde mir die Links mal anschauen, die du mir zur Verfügung gestellt hast.

An dem Punkt, wo ich gemerkt hab, ich werde gefühlte 100 Variablen brauchen und ein riesiges „if - else“ - Monster erschaffen muss, habe ich mir gedacht, dass es einfacher gehen muss und mich an euch gewendet :smiley:

Also so komplex muss es ja nicht sein, das könnte z.b. als erster Anfang dann so aussehen, das SQL Statement
[SQL]
SELECT
AVG(hoehe),
AVG(volumen)
FROM
pakete
WHERE
hoehe>100
AND
hoehe<200
AND
zeitstempel>6:00:00
AND
zeitstempel<7:00:00
[/SQL]

HSQLDB
könnte als DB genutzt werden,

von
Rheinwerk Computing :: Java ist auch eine Insel - 17 Einführung ins Datenbankmanagement mit JDBC
aus klauend ein kleines Beispiel mit einer reinen Memory-Datenbank, in der Anwendung erstellt und geschlossen:
[spoiler]```
public class Test2 {
public static void main(String args[]) {
try {
Class.forName(“org.hsqldb.jdbcDriver”);
} catch (ClassNotFoundException e) {
System.err.println(“Keine Treiber-Klasse!”);
return;
}

    Connection con = null;
    try    {
        con = DriverManager.getConnection("jdbc:hsqldb:mem:test;shutdown=true", "sa", "");
        Statement stmt = con.createStatement();

        stmt.executeUpdate("create table Customer (PersonID int,LastName varchar(255),FirstName varchar(255) )");
        stmt.executeUpdate("insert into Customer values(1,'X','A')");
        stmt.executeUpdate("insert into Customer values(12,'Z','C')");
        stmt.executeUpdate("insert into Customer values(2,'Y','B')");

        ResultSet rs = stmt.executeQuery("SELECT * FROM Customer order by PersonID");

        while (rs.next())
            System.out.printf("%s, %s %s", rs.getString(1), rs.getString(2), rs.getString(3));

        rs = stmt.executeQuery("SELECT avg(PersonID) FROM Customer"); // int-Durchschnitt, gerundet
        while (rs.next())
            System.out.println("Schnitt: " + rs.getDouble(1));

        rs.close();
        stmt.close();
    } catch (SQLException e)  {
        e.printStackTrace();
    }
    finally    {
        if (con != null) try   {
            con.close();
        }   catch (SQLException e)   {
            e.printStackTrace();
        }
    }
}

}


allgemein ist Beschäftigung mit DB zu begrüßen, hier aber vielleicht etwas zu umfangreich,
ein einzelnes  `AND  zeitstempel>6:00:00  AND  zeitstempel<7:00:00` wird nicht reichen wenn man beliebige Daten auswerten will,
eine Schleife über alle 24 Stunden des Tages sicher auch nicht, ist recht komplex da zu gruppieren usw., 

hier kommt soviel zusammen dass man ruhig die Mächtigkeit von Java zu beliebigen Code nutzen kann,
zudem dann durchaus die Chance, überhaupt nicht alle Daten in Objekt-Form oder als DB-Eintrag listen zu müssen sondern direkt beim Einlesen zu summieren

gruppieren ist das Problem, man hat ja sowohl Tage, Stunden und mm,

auch nicht viel einfacher:

[SPOILER]```import java.io.;
import java.util.
;

/**

  • @author CB
    */
    public class Temp {

    private static HWLVPaket pakete = {
    new HWLVPaket(true),
    new HWLVPaket(false),
    new HWLVPaket(true),
    new HWLVPaket(false),
    new HWLVPaket(true),
    new HWLVPaket(false),
    new HWLVPaket(true),
    new HWLVPaket(false)
    };

    public static void main(String args) throws IOException {
    int i = 0;
    BufferedReader br = new BufferedReader(new FileReader(„D:\Downloads\20150820_EM06.txt“));
    String line = br.readLine();
    while ((line = br.readLine()) != null) {
    String split = line.split(„;“);
    System.out.println(Arrays.toString(split));
    if (split.length == 11) {
    int h = Integer.parseInt(split[7]), w = Integer.parseInt(split[8]), l = Integer.parseInt(split[9]), v = Integer.parseInt(split[10]);
    pakete[0].add(h);
    pakete[1].add(h);

             pakete[2].add(w);
             pakete[3].add(w);
    
             pakete[4].add(l);
             pakete[5].add(l);
    
             pakete[6].add(v);
             pakete[7].add(v);
         }
         //i++;
         if (i == 10) {
             break;
         }
     }
     br.close();
    
     for (HWLVPaket p : pakete) {
         System.out.println(p.getAvr());
     }
    

    }
    }

class Paket {

}

class HWLVPaket {

boolean mit0;
int anz = 0;
int sum = 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;

public HWLVPaket(boolean mit0) {
    this.mit0 = mit0;
}

public void add(int i) {
    if (mit0 || i >= 1) {
        anz++;
        sum += i;
        min = i < min ? i : min;
        max = i > max ? i : max;
    }
}

public double getAvr() {
    return sum / (double) anz;
}

}```[/SPOILER]

Danke @Unregistered für die SQL-Anfrage.

Ließe sich alles (schon in einer Datei) auch mit SQLite machen.