2016-05-26 9 views
3

Hintergrund: Ich versuche, Statistiken für Krankenwagen mit Apache Commons Math zu bestimmen. Ich bin in der Lage, sehr einfache univariate Statistiken für einen Krankenwagen zu machen, aber ich bleibe stecken, wenn ich Statistiken für alle Krankenwagen in meiner Flotte bestimmen will.Schleife durch eine Ergebnismenge, um Durchschnitte nach Gruppe zu erzeugen

Ziel: Mein Ziel ist es, eine Basisergebnismenge mit JDBC zu generieren, analysiert dann die Informationen in statistische Informationen. Zum Beispiel würde ich gerne die Ergebnismenge nehmen und es wie eine Tabelle aussehen lassen, die den Krankenwagen zeigt, Durchschnitt für 2014, Durchschnitt für 2015, um die Überschrift zu sein. Die die Tabelle Details würden jeden Krankenwagen zeigen, und die Mittelwerte für jeden Header

<table> 
 
<tr><th>ambulance</th><th>average response time for year 2014</th><th>average response time for year 2015</th></tr> 
 
<tr><td>Medic1</td><td>62</td><td>74</td></tr> 
 
<tr><td>Medic2</td><td>83</td><td>79</td></tr> 
 
<tr><td>Medic3</td><td>68</td><td>71</td></tr> 
 
</table>

Versuchte Pseudo-Code: Der Pseudo-Code würde wie folgt aussehen; 1.) Weisen Sie eine Variable für die durchschnittliche Antwortzeit des Kalenderjahres 2014 zu. 2.) durchlaufen Sie alle Ambulanzen in der Ergebnismenge, wenn das Kalenderjahr 2014 ist, dann berechnen Sie einen Durchschnitt. 3.) eine Variable für die durchschnittliche Antwortzeit des Kalenderjahres 2015 zuweisen. 4.) Schleife durch alle Krankenwagen und wenn das Kalenderjahr 2015 ist, dann berechnen Sie den Durchschnitt. 5.) Ausgang der Krankenwagen, durchschnittliche Antwortzeit für das Jahr 2014, die durchschnittliche Antwortzeit für das Jahr 2015

Kommentare: Dies wäre ein guter Anfang sein. Zumindest die Logik und das Format wären vorhanden, um differenziertere Analysen durchzuführen, wie zum Beispiel die Unterschiede Jahr für Jahr zu bestimmen. Aber ich stecke fest. Ich bin nicht sicher, wie man eine Wiederholung über jeden Krankenwagen durchführt, um den Durchschnitt zu erzeugen.

Ich kann SQL-Abfragen schreiben, die Durchschnittswerte für jeden Krankenwagen generieren würden. Aber ich möchte Apache Commons Math verwenden, weil es Skew, Kurtosis und andere Maßnahmen bietet. Was Sie oberhalb dieses Absatzes sehen, ist ein vereinfachtes Beispiel für etwas Komplexeres.

Java-Code:

package EMSResearch; 

import java.sql.*; 
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; 

public class EMSResearch 
{ 

    public static void main(String[] args) 
    { 
     Connection conn = null; 
     Statement stmt = null; 
     try 
     { 
      conn = DriverManager.getConnection("jdbc:sqlserver://MyDatabase;database=Emergencies;integratedsecurity=false;user=MyUserName;password=MyPassword"); 
      stmt = conn.createStatement(); 
      String strSelect = "SELECT EmergencyID, YearOfCall, ResponseTime, Ambulance"; 
      ResultSet rset = stmt.executeQuery(strSelect); 

      DescriptiveStatistics ds = new DescriptiveStatistics(); 
/*the following code does the job of generating average response time for Medic1 for year 2015. But I want it to loop through and get all the ambulances for year 2015*/ 
      while (rset.next()) 
      { 
       if (rset.getString("Ambulance").equals("Medic1") && rset.getInt("YearOfCall") == 2015) 
       { 
        String event = rset.getString("I_EventNumber"); 
        int year = rset.getInt("YearOfCall"); 
        int responseTime = rset.getInt("ResponseTime"); 
        String truck = rset.getString("Ambulance"); 
        ds.addValue(responseTime); 
       } 
      } 
      System.out.println("mean average value " + ds.getMean()); 


     } catch (SQLException ex) 
     { 
      ex.printStackTrace(); 
     } finally 
     { 
+0

Verwenden Sie stattdessen die [SQL-Fensterfunktionen] (https://msdn.microsoft.com/en-us/library/ms189461%28v=sql.110%29.aspx). –

+0

Das ist, was ich normalerweise tue, aber in diesem Fall wollte ich Apache Commons Math verwenden, weil es Methoden für Skew und Kurtosis hat. Sobald ich geübt bin, kann ich noch viel mehr Statistikfunktionen ausführen. –

Antwort

0

So etwas wie dies helfen könnte. Wenn Sie eine Karte verwenden, um alle Daten für alle Jahre und Lastwagen zu speichern, können Sie alles bekommen, was Sie brauchen, denke ich. Dieser Code ist nicht vollständig gebacken, aber es ist ziemlich süß im Konzept, denke ich.

private static void getstats(ResultSet rset) throws SQLException { 
    Map<Integer, Map<String, DescriptiveStatistics>> stats = new HashMap<>(); 
    while (rset.next()) { 

     String event = rset.getString("I_EventNumber"); 
     int year = rset.getInt("YearOfCall"); 
     int responseTime = rset.getInt("ResponseTime"); 
     String truck = rset.getString("Ambulance"); 
     if (stats.containsKey(year)) { 
     Map<String, DescriptiveStatistics> get = stats.get(year); 
     if (get.containsKey(truck)) { 
      get.get(truck).addValue(responseTime); 
     } else { 
      Map<String, DescriptiveStatistics> newmap = new HashMap<>(); 
      DescriptiveStatistics newDs = new DescriptiveStatistics(); 
      newDs.addValue(responseTime); 
      newmap.put(truck, newDs); 
     } 

     } else { 

     Map<String, DescriptiveStatistics> newmap = new HashMap<>(); 
     DescriptiveStatistics newDs = new DescriptiveStatistics(); 
     newDs.addValue(responseTime); 
     newmap.put(truck, newDs); 
     stats.put(year, newmap); 
     } 

    } 
    for(Integer year : stats.keySet()){ 
     for(String truck : stats.get(year).keySet()){ 
     DescriptiveStatistics ds = stats.get(year).get(truck); 
     /**do stuff with the ds for this year and this truck**/ 

     } 
    } 

    } 
+0

Danke markg: Ich werde meine College-Lehrbücher herausziehen und auf Karten lesen. Ich bin nur ein Anfänger Programmierer. Übrigens, ich denke, Tommy Boy war ein komischer Film. –

+0

Karten sind nur Schlüssel-> Wertstrukturen. Die get (...) -Methode nimmt den Schlüssel und gibt den Wert zurück, wie auch immer Sie ihn in Ihren generischen Argumenten angeben. Karten sind mächtig, ich empfehle Ihnen, sie kennenzulernen! – markg

0

Wie markg sagte ein Map wird Ihnen sehr helfen. Um nur ein wenig hinzuzufügen, würde ich auch Ihre Daten sinnvoll gruppieren. Zum Beispiel enthält Ihre aktuelle Implementierung dieser:

DescriptiveStatistics ds = new DescriptiveStatistics(); 

while (rset.next()) 
{ 
    if (rset.getString("Ambulance").equals("Medic1") && rset.getInt("YearOfCall") == 2015) 
    { 
     String event = rset.getString("I_EventNumber"); 
     int year = rset.getInt("YearOfCall"); 
     int responseTime = rset.getInt("ResponseTime"); 
     String truck = rset.getString("Ambulance"); 
     ds.addValue(responseTime); 
    } 
} 

Was sind Sie im Wesentlichen jetzt tun, ist zu bestimmen, ob die Daten eine bestimmte Kriterien erfüllt, fügen Sie es zu Ihrem einzelnen Datensatz. Wenn Sie jedoch ein anderes Kriterium überprüfen möchten, müssen Sie ein anderes Dataset initialisieren, eine weitere if-Anweisung hinzufügen und den Code dort kopieren. es ist nicht skalierbar.

Stattdessen betrachten Sie ein Objekt erstellen, die Sie gruppieren Sie Ihre Daten verwenden können:

public class DataPoint { 
    // Consider private members with public getters/setters. 
    public String ambulance; 
    public int year; 

    public DataPoint(String ambulance, int year) { 
     this.ambulance = ambulance; 
     this.year = year; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result 
       + ((ambulance == null) ? 0 : ambulance.hashCode()); 
     result = prime * result + year; 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     DataPoint other = (DataPoint) obj; 
     if (ambulance == null) { 
      if (other.ambulance != null) 
       return false; 
     } else if (!ambulance.equals(other.ambulance)) 
      return false; 
     if (year != other.year) 
      return false; 
     return true; 
    } 
} 

Die hashCode() und equals() Überschreibungen sind wichtig, aber tangential zu dieser Diskussion. Im Grunde stellen sie sicher, dass die Map zwei verschiedene Objekte mit den gleichen Parametern finden und bestimmen kann.

Mit unserem neuen DataPoint-Objekt können wir jetzt Daten, die wir erhalten, bestimmten Datensätzen zuordnen. So Ihre Implementierung ich oben beschrieben würde ersetzt werden:

Map<DataPoint, DescriptiveStatistics> map = new HashMap<DataPoint, DescriptiveStatistics>(); 

while (rset.next()) 
{ 
    // Get parameters we differentiate based on. 
    String truck = rset.getString("Ambulance"); 
    int year = rset.getInt("YearOfCall"); 

    // Create the data point. 
    DataPoint point = new DataPoint(truck, year); 

    // Get data set for point; if it doesn't exist, create it. 
    if (map.get(point) == null) { 
     map.put(new DescriptiveStatistics()); 
    } 
    DescriptiveStatistics ds = map.get(point); 

    // Add the data of interest to the given data set. 
    int responseTime = rset.getInt("ResponseTime"); 
    ds.addValue(responseTime); 
} 

Wenn die while-Schleife beendet ist, werden Sie eine Karte mit einer Abbildung von spezifischen Datenpunkte und ihre zugehörigen Datensätzen gefüllt haben. Von dort iterieren nur durch die Map-Einträge und Sie können alles, was Sie mit den Datensätzen tun wollen:

for (Entry<DataPoint, DescriptiveStatistics> entry : map.entrySet()) 
... 

Hoffnung, die ein wenig verdeutlicht.