Das Strategy Design Pattern

Einführung

Das Strategy Design Pattern hat die Aufgabe Strategien zu kapseln und austauschbar zu machen.
In unserem praktischen Beispiel möchte ich das mit Hilfe eines Grtengrundstückes darstellen. Der Besitzer des Gartengrundstückes besitzt einen Hund. Diesem Hund wurden verschiedene Strategien beigebracht.

Diese Strategien des Hundes sind im einzelnen:

  • nähert sich eine Katze dem Gartenzaun, so hat er ( der Hund ) verhalten zu bellen
  • betritt eine Katze den Garten so hat der Hund deutlich zu bellen
  • erreicht diese Katze das Gartenhaus so hat der Hund laut zu bellen und die Zähne zu fletchen

Da der Besitzer des Hundes sich nicht im klaren ist ob das Verhalten des Hundes korrekt ist,
möchte er die oben genannten Strategien ändern und gegebenenfalls durch weitere Strategien ergänzen.

Bilden wir unseren Hundes in einer Klasse ab. Dazu erstellen wir die Klasse 'hund' und erweitern diese Klasse durch 'ModelData'. Dadurch erstellen wir ein Standardmodel des Framework Frink2.

Die Skripte der Model finden sie im Framework Frink2.

Als erstes erstellen wir das Basismodel 'hund'.

Klasse Hund

class hund extends \models\ModelData
{

    public function reaktion()
    {
        if($this->data['abstandZumGartenzaun'] == 0)
            $this->data['reaktionHund'] = $this->pimple['knurrenderHund']->bellen();
        elseif( ($this->data['abstandZumGartenzaun'] > 0) and ($this->data['abstandZumGartenzaun'] < 10) )
            $this->data['reaktionHund'] = $this->pimple['bellenderHund']->bellen();
        else
            $this->data['reaktionHund'] = $this->pimple['randalierenderHund']->bellen();
    }

}

Das verhalten des Hundes kapseln wir in einzelnen Klassen. Diese Klasse haben eine einheitliche Schnittstelle 'bellen()'. Durch das Interface 'interfaceHundBellen' wird in den Strategieklassen das einheitliche Interface garantiert.

Interface interfaceHundBellen

interface interfaceHundBellen
{
    public function bellen();
}

Die einzelnen Strategien des Hundes werden in Strategie - Klassen gespeichert.

Strategie Klassen

class knurrenderHund implements \models\interfaceHundBellen
{
    public function bellen()
    {
        return 'Hund knurrt';
    }
}

class bellenderHund implements \models\interfaceHundBellen
{
    public function bellen()
    {
        return 'Hund bellt';
    }
}

class randalierenderHund implements \models\interfaceHundBellen
{
    public function bellen()
    {
        return 'Hund bellt und fletcht die Zähne';
    }
}

Unser Strategie Pattern in der praktischen Anwendung:

Im '__construct()' des Controller übergeben wir die Model an den DI Container Pimple.
Dadurch werden die Model / Strategie Model in allen Klassen verfügbar.

 public function __construct($controllerName, $actionName)
{
    // Vorbereitung des Pimple Container, Singleton Pattern !
    $models = [
        'hund' => function ($pimple) {
            return new \models\hund($pimple);
        },
        'knurrenderHund' => function ($pimple){
            return new \models\knurrenderHund();
        },
        'bellenderHund' => function ($pimple){
            return new \models\bellenderHund();
        },
        'randalierenderHund' => function ($pimple){
            return new \models\randalierenderHund();
        }
    ];

    parent::pimple($models);
}

Im Controller existiert eine Action mit dem Namen 'strategyPattern()'.
In dieser Action wird die Strategie des Hundes in Abhängigkeit des Abstand
der Katze vom Gartenzaun geändert.
Und letztendlich wird das Templat mit 'templat()' angezeigt.

public function strategyPattern()
{
    try {

        /** @var $modelHund \models\hund */
        $modelHund = $this->pimple['hund'];

        // Katze ist am Gartenzaun
        $modelHund['abstandZumGartenzaun'] = 0;
        $modelHund->reaktion();
        $reaktion = $modelHund['reaktionHund'];

        // Katze ist im Garten
        $modelHund['abstandZumGartenzaun'] = 5;
        $modelHund->reaktion();
        $reaktion = $modelHund['reaktionHund'];

        // Katze ist am Gartenhaus
        $modelHund['abstandZumGartenzaun'] = 11;
        $modelHund->reaktion();
        $reaktion = $modelHund['reaktionHund'];

        $this->template();
    }
        // eigene Exception
    catch (\tools\frinkError $e) {
        throw $e;
    } // Exception anderer Klassen
    catch (\Exception $e) {
        throw $e;
    }
}

Das Decorator Design Pattern

Einführung

Das Decorator Design Pattern ermöglicht es neue Methoden zur Laufzeit zu einem Objekt hinzuzufügen. In einem simplen Beispiel möchte ich ihnen die Funktionsweise dieses Pattern zeigen. Zur Umsetzung des Pattern verwende ich die Möglichkeiten von Php 5.4. Für die bildliche Darstellung verwende ich keine Klasse 'Auto'.
Was eigentlich völlig unmöglich ist !

Zur Darstellung des Docorater Pattern verwende ich eine Geburtstagstorte.
Wie immer findet sie das Skript im Framework Frink2 - Dekoration Pattern.

Klasse Torte

Ich erstelle als erstes die Basisklasse 'Torte'. Durch die Erweiterung der Basisklasse mit '\models\ModelData' entsteht ein Standard-Model für das Framework Frink2

class Torte extends \models\modelBasis
{
    /**
     *
     * @return string
     */
    public function zuckerGuss()
    {
        return 'Zuckerguss';
    }

    /**
     * @return string
     */
    public function hasFruechte()
    {
        return 'Fruechte';
    }

    /**
     * @return string
     */
    public function hasKalorien()
    {
        return 'gewaltig Kalorien';
    }
}

erweitern des Standard Model

Diese Basisklasse wird um ein Trait erweitert. Dieser Trait ermöglicht die dynamische Erweiterung unseres Model um weitere Methoden.

class TorteMitDekoration extends \models\Torte
{
    use \traits\addMethods;

}

Trait

Der Trait beinhaltet folgende Methoden.

trait addMethods
{
    private $methods = array();

    public function addMethod($methodName, $methodCallable)
    {
        if (!is_callable($methodCallable)) {
            throw new frinkError('zweite Parameter muss eine aufrufbare Funktion beinhalten', 3);
        }

        // $this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
        $this->methods[$methodName] = $methodCallable;
    }

    public function __call($methodName, array $args)
    {
        if (isset($this->methods[$methodName])) {
            return call_user_func_array($this->methods[$methodName], $args);
        }

        throw new frinkError('Diese Methode ist nicht vorhanden');
    }
}

Unser Dekoration Pattern in der praktischen Anwendung:

Im '__construct()' des Controller übergeben wir das Model an den DI Container Pimple.

 public function __construct($controllerName, $actionName)
{
    // Vorbereitung des Pimple DI Container
    $models = [
        'torteMitDekoration' => function ($pimple) {
            return new \models\TorteMitDekoration($pimple);
        }
    ];

    parent::pimple($models);       
}

Im Controller existiert eine Action mit dem Namen 'decorationPattern()'

public function decorationPattern()
{
    try {
        // Dekorieren der Torte
        $this->torteVorbereiten();

        // Geburtstagsfeier
        $this->Geburtstagsfeier();

        $this->template();
    }
        // eigene Exception
    catch (\tools\frinkError $e) {
        throw $e;
    } // Exception anderer Klassen
    catch (\Exception $e) {
        throw $e;
    }
}

Diese Action ruft drei Methoden im Controller auf.
Als erstes wird die Klasse in der Methode 'torteVorbereiten()' aufgerufen.

protected function torteVorbereiten()
{
    // PhpStorm mitteilen welches Model verwendet wird
    /** @var $torteMitDekoration \models\TorteMitDekoration */
    $torteMitDekoration = $this->pimple['torteMitDekoration'];

    // dynamisches hinzufügen von Methoden
    $torteMitDekoration->addMethod('kerzen', function(){
        return 'Kerzen verwenden';
    });

    $torteMitDekoration->addMethod('anzuenden', function(){
        return 'Kerzen anzuenden';
    });

    $torteMitDekoration->addMethod('auspusten', function (){
        return 'Kerzen auspusten';
    });

    // die Torte in den Kühlschrank stellen
    $this->pimple['torteMitDekorationUndKerzen'] = $torteMitDekoration;

    return;
}

In der zweiten Methode 'Geburtstagsfeier()' wird das Dekoration Pattern genutzt.

protected function Geburtstagsfeier()
{
    // Torte aus dem Kühlschrank holen

    /** @var $torteMitDekorationUndKerzen \models\TorteMitDekoration */
    $torteMitDekorationUndKerzen = $this->pimple['torteMitDekorationUndKerzen'];

    // Kerzen aufstecken
    $test = $torteMitDekorationUndKerzen->kerzen();

    // Kerzen anzünden
    $test = $torteMitDekorationUndKerzen->anzuenden();

    // Kerzen auspusten
    $test = $torteMitDekorationUndKerzen->auspusten();

    // Den Frauen klar machen das die Torte zu viele Kalorien hat :-)
    $test = $torteMitDekorationUndKerzen->hasKalorien();

    return;
}

Und letztendlich wird das Templat mit 'templat()' angezeigt.

Das Prototype Design Pattern

Einführung: Eine spezielle Art des Php Design Pattern ist die Verwendung eines prototypischen Objektes und die Vervielfältigung dieses Prototypes. Für die Erzeugung des Prototypes verwenden wir den DI Container Pimple.

Ausgehend von meinen Erläuterungen zur Verwendung des DI Container Pimple beginne ich mit der Erstellung eines Factory Pattern mit Hilfe des DI Container Pimple. Für unser Beispiel verwenden wir als Stammklasse die Klasse 'Car'.

<?php

namespace models;

/**
* Erstellen eines Car und deren Nutzung als Php Design Pattern
*
* @author Stephan Krauß
* @copyright Stephan Krauss
* @lisence Stephan Krauß
* @date 26.06.2016
*
* @package models
*/

class Car extends \models\ModelData
{

}

Diese Klasse wurde als Standardklasse des Framework Frink2 geschaffen. Durch die Erweiterung der Klasse 'Car' mit dem Standard Model 'ModelData' haben wir die Methoden '__construct()' , 'getAllData()' und 'setAllData()' zur Verfügung. Gleichzeitig können wir die SPL Möglichkeiten von ArrayAccess nutzen.

class ModelData implements \ArrayAccess
{
    use \traits\arrayAccess;

    public $data = [];
    protected $pimple;

    /**
     * ModelData constructor.
     *
     * @param $pimple
     */
    public function __construct(\Pimple\Container $pimple)
    {
        $this->pimple = $pimple;
    }

    /**
     * @return array
     */
    public function getAllData()
    {
        return $this->data;
    }

    /**
     * @param array $data
     * @return ModelData
     */
    public function setAllData(array $data)
    {
        $this->data = $data;

        return $this;
    }
}

Die Methoden von ArrayAccess sind im Trait 'arrayAccess' definiert.

trait arrayAccess
{
    /**
     * @param $offset
     * @param $value
     */
    public function offsetSet($offset, $value)
    {
        if(is_null($offset)){
            $this->data[]=$value;
        } else{
            $this->data[$offset]=$value;
        }
    }

    /**
     * @param $offset
     *
     * @return bool
     */
    public function offsetExists($offset)
    {
        return isset($this->data[$offset]);
    }

    /**
     * @param $offset
     */
    public function offsetUnset($offset)
    {
        unset($this->data[$offset]);
    }

    /**
     * @param $offset
     *
     * @return null
     */
    public function offsetGet($offset)
    {
        return isset($this->data[$offset]) ? $this->data[$offset] : null;
    }
}

Sie finden diese Skripte unter github.com/StephanKrauss/frink.

__construct() des Controller

// anlegen des Model Car als Factory Pattern, kann im __construct() erfolgen
$pimple = new \Pimple\Container();

$pimple['car'] = $this->pimple->factory(function ($pimple) {
    return new \models\Car($pimple);
});

$this->pimple = $pimple;

Action des Controller

// abrufen des Model aus dem DI Container Pimple
// und PhpStorm das Model mitteilen

/** @var $modelCar \models\Car */
$modelCar = $this->pimple['car'];

// befüllen des Model 'Car' mit den Eigenschaften des Prototypes
$modelCar['engine'] = 'VW Diesel 2.0';
$modelCar['gas'] = 'diesel';
$modelCar['color'] = 'blau';
$modelCar['logo'] = 'Fußball-EM 2016';

// überprüfen des Prototype
var_dump($modelCar->getAllData());

// ergibt folgendes Ergebnis
// array (size=4)
  // 'engine' => string 'VW Diesel 2.0' (length=13)
  // 'gas' => string 'diesel' (length=6)
  // 'color' => string 'blau' (length=4)
  // 'logo' => string 'Fussball 2016' (length=13)

// erstellen einer Kleinserie aus dem Prototype
// und abstellen der produzierten Fahrzeuge
$parkplatz = [];

for($i=1; $i < 10; $i++) {
    $parkplatz[$i] = clone $modelCar;
}

Zusammenfassung:

Durch die konsequente Nutzung des DI Container kann die Erstellung der Erzeugungspatter in Php extrem vereinfacht werden. Alle modernen Frameworks verfügen über einen DI Container. Die Weitergabe der effektiven Nutzung dieser DI ist ein lohnendes Gesprächsthema im wöchentlichen Kreativfrühstück.

strukturierte Applikationen mit Pimple I

ursprünglicher Artikel von Giuseppe Mazzapica

Zusammenfassung

Die Verwendung von Pimple ( Version: 3 ) erlaubt die Schaffung von skalierbaren und testbaren Anwendungen in Php.

Pimpel ist es ein kleiner, aber leistungsstarke DI -Container. Seine Stärke liegt in der Einfachheit. Pimple kann Services registrieren die dann abgerufen werden können. Pimple hat automatische Auflösung via Reflection API , keine fortschrittliche Sache wie Service - Bindung über Annotations ...

Zum registrieren eines Service wird eine closure function geschrieben die eine Instance des Service zurück gibt. Die function selbst bekommt als Parameter den DI Container. Durch dieses Verfahren ist es möglich auf Grundlage bereits bestehender Service neue Service zu schreiben.

Verwendung des DI Container Pimple

$pimple['foo'] = function($pimple) {
    return new Foo;
 };

$pimple['bar'] = function($pimple) {
   return new Bar($pimple['foo']);
};

Im obigen Beispiel wird eine Instanz der Klasse 'Foo' in die Klasse 'Bar' übergeben. Hiebei handelt es sich um eine Konstruktor Injektion. Die Besonderheit besteht darin das die Service erst dann erstellt werden wenn sie benötigt werden. Daher spielt die Reihenfolge der Erstellung der Service keine Rolle.

Wenn Pimple ertellt wird, dann ist es möglich ein Array von Werten zu übergeben. Im Framework Frink2 ist dieses Verfahren die Hauptform der Erstellung von Objekten. Die erstelletn Objekte mit diesem Verfahren sind Objekte nach dem Design Pattern Singleton.

$pimple = new Pimple\Container(array(
   'foo' => function() {
     return new Foo();
   },
   'bar' => function($pimple) {
     return new Bar($pimple['foo']);
   }
 ));

Dies ist ein guter Ansatz weil dadurch alle Objekte zentral erstellt werden. Diese Objekte können zentral erstellt werden und bei Bedarf überschrieben werden. Im Framework Frink2 gibt es pro Controller eine Methode in der Pimple verwaltet wird. Durch die konsequente Übergabe des DI Container Pimple an alle Models stehen jederzeit alle Objekte zur Verfügung. Eine mögliche Unübersichtlichkeit der Objekte kann durch eine spezielle Funktion des Editors gemildert werden.

ein besserer Ansatz zur Nutzung von Pimple

Statt dem setzen von allen Objekten im Konstruktor des DI Container empfiehlt sich die Verwendung als Service Provider.Ab der Version 3 von Pimple sollte dieser Ansatz verwendet werden. Dazu steht die 'register()' Methode zur Verfügung. Die Services sind Klassen die nur eine Aufgabe haben. Das registrieren von Services im Container. Pimple verwendet dazu nur die 'register()' Methode.

// FooServiceProvider.php

 class FooServiceProvider implements Pimple\ServiceProviderInterface
{

        public function register(Pimple\Container $pimple)
        {
            $pimple['foo'] = function(){
             return new Foo();
            };

               $pimple['bar'] = function($pimple)
            {
                 return new Bar($pimple['foo']);
            };

         }
}

 // in another file...

 $container = new Pimple\Container();
 $container->register(new FooServiceProvider());

 // and then 
    echo get_class($container['bar']);
 // Bar 

ein Beispiel

// file: /src/Words/WordInterface.php
namespace GM\HelloWorld\Words;

interface WordInterface {
   public function output();
 }

 // file: /src/Words/Hello.php
 namespace GM\HelloWorld\Words;

 class Hello implements WordInterface
 {
       public function output(){
         return 'Hello';
       }
 }

 // file: /src/Words/World.php
 namespace GM\HelloWorld\Words;

 class World implements WordInterface
 {
       public function output()
       {
             return 'World';
       }
 }

Bis hierher dürfte es keine Probleme geben ?

Um diese Objekte global nutzbar in der Anwendung zu machen schreiben wir einen Service Provider.

// file: /src/Providers/WordsServiceProvider.php
namespace GM\HelloWorld\Providers;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use GM\HelloWorld\Words as W;

class WordsServiceProvider implements ServiceProviderInterface
{
     public function register(Container $pimple)
     {
           $pimple['hello'] = function(){
                 return new W\Hello();
            };

           $pimple['world'] = function()
           {
                 return new W\World();
           };
       }
}

Wir sehen an dieser Stelle dass unsere Applikation wächst. Durch die Verwendung der Klasse 'WordsServiceProvider' und der Übergabe der Klassen 'Hello' und 'World' als Service an die 'Provider Klasse WordsServiceProvider' sind die Service jederzeit verfügbar.

ZUr Verbesserung dieser Funktionalität schreiben wir eine kleine Helper Funktion.

// file: /helpers.php
 namespace GM\HelloWorld;

 /**
 * On first call instantiate Pimple container and register the providers
 * loading them form a file. On subsequent calls returns container itself   
 * or a service, if $which param is a service id.
 * @param string|void $which Service id to retrieve
 * @staticvar \Pimple\Container $app Container instance
 * @return mixed
 * @throws \InvalidArgumentException If $which param isn't null but service is not defined
 */

 function app($which = null)
 {
       static $app = null;

       if (is_null($app))
       {
             $app = new \Pimple\Container;
             $providers = (array) require __DIR__.'/providers.php';

             array_walk($providers, function($class, $i, $app)
             {
               class_exists($class) AND $app->register(new $class);
             }, $app);
          }

           return is_null($which) || ! is_string($which) ? $app : $app[$which];

 }

 // file: /providers.php

 return array(
            '\\GM\\HelloWorld\\Providers\\WordsServiceProvider'
         );

Wenn die Helper - Funktion das erste Mal aufgerufen wird, erstellt die Funktion eine Instanz von Pimple. In einem zweiten Schritt lädt die Helper Funktion die Datei 'providers.php'. In der 'providers.php' befindet sich ein Array der Service - Provider -Klassen. Diese Service - Provider - Klassen werden in Pimple registriert. Bei jedem nachfolgenden Aufruf gibt die Funktion den DI Container Pimple zurück oder bei dem vorhandensein des Parameter '$which' den betreffenden Service zurück.

Mit dieser Funktion kann man überall in der Anwendung einen Service erhalten, einen Service registrieren oder die Service Provider laden. Wenn unsere Anwendung wächst können wir verschiedene 'providers.php' verwenden. Es entsteht ein übersichtliches und verständliches System. Durch das einfügen oder ändern einer Zeile in einer der 'provider.php' können weitere Service geladen werden ohne anderen Code zu verändern.

Verwendung der Javascript Bibliothek 'gist-embed.js' zur Darstellung der 'Gist' in einem Blog

Darstellung eines Gist in der Homepage, https://github.com/blairvanderhoof/gist-embed

Eine Quelle der Business - Logik des Team ist eine gemeinschaftlich geschaffene Gist - Sammlung. Diese wird gepflegt entweder
über den Editor (PhpStorm) oder aber über die App gistboxapp.
Um diese Gist in einer Homepage darzustellen empfiehlt sich der Einsatz der Javascript Bibliothek 'gist-embed'.
Nachfolgend einige Beispiele für die Darstellung eines 'Gist' in einem Blog.

  • laden eines Gist: [code data-gist-id="8fa840fe8ace582bddb6"][/code]

  • laden eines Gist, Fußzeile entfernt: [code data-gist-id="8fa840fe8ace582bddb6" data-gist-hide-footer="true"] [/code]

  • laden eines Gist Fußzeile und Zeilennmummer entfernt: [code data-gist-id="8fa840fe8ace582bddb6" data-gist-hide-footer="true" data-gist-hide-line-numbers="true"][/code]

  • laden eines Gist mit markierten Zeilen: [code data-gist-id="8fa840fe8ace582bddb6" data-gist-highlight-line="2-9,13" data-gist-hide-footer="true"][/code]

Kontrolle der Softwarequalität im Editor PhpStorm

Motivation

Neben einer schnellen Entwicklung einer Applikation nach Kundenvorgaben ist ein entscheidendes Kriterium die Softwarequalität. Dazu empfiehlt es sich im Team ein mehrstufiges System der Kontrolle der Softwarequalität einzuführen. Die nachfolgenden Informationen beziehen sich auf die erste Stufe der Kontrolle der Softwarequalität. Die eigenständige Kontrolle der Qualität der erstellten Skripte. Diese Skripte werden während der Erstellung mit geeigneten Tools automatisch überprüft und nötigenfalls korrigiert.

Während der täglichen Arbeit verwende ich den Php Editor PhpStorm. Dieser Editor kann mit 3 Tools der Softwarekontrolle ergänzt werden.

  1. Das erste Tool ist PHPLOC
  2. Das zweite Tool ist ist der PHP Mess Detector
  3. Ein weiteres Tool ist PHP CodeSniffer

Die nachfolgenden Tipps und Tricks zeigen den Einsatz dieser Tools im im PhpStorm. Ziel ist es mit einfachen Mitteln die Softwarequalität durch eine Eigenkontrolle zu verbessern.

1. Verwendung des PHPLOC im Editor PhpStorm

Installation des PHPLOC und Anwendung

Javascript Bibliothek underscore.js (Vers.: 1.8.3)

Dokumentation (befindet sich in permanenter Überarbeitung)

Bearbeitung von Kollektionen

Funktion each

Iterates over a list of elements, yielding each in turn to an iteratee function. The iteratee is bound to the context object, if one is passed. Each invocation of iteratee is called with three arguments: (element, index, list). If list is a JavaScript object, iteratee's arguments will be (value, key, list). Returns the list for chaining.

Alias: forEach

Beispiele:

_.each(list, iteratee, [context]);

-

_.each([1, 2, 3], alert);

-

_.each({one: 1, two: 2, three: 3}, alert);

-

_.each({one: 1, two: 2, three: 3}, test);

function test(item)
{
    console.log(item);
}

Funktion map

Produces a new array of values by mapping each value in list through a transformation function (iteratee). The iteratee is passed three arguments: the value, then the index (or key) of the iteration, and finally a reference to the entire list.

Alias: collect

Beispiele:

_.map(list, iteratee, [context]);

-

var result = [];

var i = 0;
_.map([1, 2, 3], function(num)
{
    result[i] = num * 3;
    i++;

    return;
});

console.dir(result);

-

var result = [];

 var i = 0;
_.map({one: 1, two: 2, three: 3},
function(num, key)
{
    result[i] = num * 3;
    i++;

    return;
});

console.dir(result);

Funktion reduce

*Also known as inject and foldl, reduce boils down a list of values into a single value. Memo is the initial state of the reduction, and each successive step of it should be returned by iteratee. The iteratee is passed four arguments: the memo, then the value and index (or key) of the iteration, and finally a reference to the entire list.

If no memo is passed to the initial invocation of reduce, the iteratee is not invoked on the first element of the list. The first element is instead passed as the memo in the invocation of the iteratee on the next element in the list. *

Alias: inject, foldl

Beispiele:

_.reduce(list, iteratee, [memo], [context])

-

var sum = _.reduce([1, 2, 3],
function(memo, num)
{
     return memo + num;
}, 0);

console.log(sum);

Funktion reduce

* Also known as inject and foldl, reduce boils down a list of values into a single value. Memo is the initial state of the reduction, and each successive step of it should be returned by iteratee. The iteratee is passed four arguments: the memo, then the value and index (or key) of the iteration, and finally a reference to the entire list.

If no memo is passed to the initial invocation of reduce, the iteratee is not invoked on the first element of the list. The first element is instead passed as the memo in the invocation of the iteratee on the next element in the list.*

Alias: inject, foldl

Beispiele:

_.reduce(list, iteratee, [memo], [context]);

-

var sum = _.reduce([1, 2, 3],
function(memo, num)
{
  return memo + num;
}, 5);

console.log(sum);
// Ergebnis => 11

Funktion reduceRight

The right-associative version of reduce. Foldr is not as useful in JavaScript as it would be in a language with lazy evaluation.

Alias: foldr

Beispiele:

_.reduceRight(list, iteratee, memo, [context]);

-

var list = [[0, 1], [2, 3], [4, 5]];

var flat = _.reduceRight(list, function(a, b)
           {
               return a.concat(b);
           }, []);

console.dir(flat);

Funktion find

Looks through each value in the list, returning the first one that passes a truth test (predicate), or undefined if no value passes the test. The function returns as soon as it finds an acceptable element, and doesn't traverse the entire list.

Alias: detect

Beispiele:

_.filter(list, predicate, [context]);

-

var five = _.find([1, 2, 3, 4, 5, 6],
           function(num){
               return num % 5 == 0;
           });

    console.log(five);

Funktion filter

Looks through each value in the list, returning an array of all the values that pass a truth test (predicate).

Alias: select

Beispiele:

_.filter(list, predicate, [context]);

-

var evens = _.filter([1, 2, 3, 4, 5, 6],
function(num){
    return num % 2 == 0;
}
);

Funktion where

Looks through each value in the list, returning an array of all the values that contain all of the key-value pairs listed in properties.

Beispiele:

_.where(list, properties);

-

var listOfPlays = [
    {title: "Cymbeline", author: "Shakespeare", year: 1612},
    {title: "The Tempest", author: "Shakespeare", year: 1611}
];

var result = _.where(listOfPlays, {author: "Shakespeare", year: 1612});

console.dir(result);

-

var listOfPlays = [{name: 'aaa', wert: 111},{name: 'bbb', wert: 222},{name: 'ccc', wert: 333}];

var result = _.where(listOfPlays,{name: 'bbb'});

console.dir(result);

Funktion findWhere

Looks through the list and returns the first value that matches all of the key-value pairs listed in properties.

Beispiele:

_.findWhere(list, properties);

-

var publicServicePulitzers = [
    {newsroom: "Freie Presse", name: 'aaa'},
    {newsroom: "The New York", name: 'bbb'},
    {newsroom: "The New York Times", name: 'ccc'},
    {newsroom: "Volksstimme", name: 'ddd'}
];

var result = _.findWhere(publicServicePulitzers, {newsroom: "The New York Times"});

console.dir(result);

Funktion reject

Returns the values in list without the elements that the truth test (predicate) passes. The opposite of filter.

Beispiele:

_.reject(list, predicate, [context]);

-

var odd = _.reject([1, 2, 3, 4, 5, 6],
        function(num){
            return num % 2 == 0;
        }
);

console.dir(odd);

Funktion every

Returns true if all of the values in the list pass the predicate truth test. Short-circuits and stops traversing the list if a false element is found.

Alias: all

Beispiele:

_.every(list, [predicate], [context]);

-

// true    
 var test = _.every([2, 4, 6], function(num)
{
    return num % 2 == 0;
});

console.log(test);

// false
test = _.every([2, 4, 5], function(num)
{
    return num % 2 == 0;
});

console.log(test);

Funktion some

Returns true if any of the values in the list pass the predicate truth test. Short-circuits and stops traversing the list if a true element is found.

Alias: any

Beispiele:

_.some(list, [predicate], [context]);

-

//Array
var arr = [66,76,67];

//Test Function
function fe(e){

    if(e == 76){
        return true;
    }
}

//Do any of them match?
var someTest = _.some(arr,fe);

//Returns True
console.log(someTest,arr);

-

var list = [null, 0, 'yes', true, false];

var result = _.some(list,
function(item)
{
    if(item == true)
        return true;
});

console.log(result, list);

Funktion contains

Returns true if the value is present in the list. Uses indexOf internally, if list is an Array. Use fromIndex to start your search at a given index.

Alias: includes

Beispiele:

_.contains(list, value, [fromIndex]);

-

var result = _.contains([1, 2, 3], 2);

console.log(result);

Funktion invoke

Calls the method named by methodName on each value in the list. Any extra arguments passed to invoke will be forwarded on to the method invocation.

Wendet eine Methode auf jedes Element der Liste an

Beispiele:

_.invoke(list, methodName, *arguments);

-

var test = _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');

console.dir(test);

Funktion pluck

A convenient version of what is perhaps the most common use-case for map: extracting a list of property values. Eine bequeme Version, vielleicht der häufigste Anwendungsfall für map. Eine Liste der Eigenschaftswerte wird extrahiert.

Beispiele:

_.pluck(list, propertyName)

-

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];

var test = _.pluck(stooges, 'name');

console.dir(test);

Funktion max

Returns the maximum value in list. If an iteratee function is provided, it will be used on each value to generate the criterion by which the value is ranked. -Infinity is returned if list is empty, so an isEmpty guard may be required.

Gibt den Höchstwert in der Liste zurück. Wenn ein iteratee Funktion vorgesehen ist, dann wird diese auf jeden Wert angewandt, um das Kriterium zu erzeugen. -Infinity Wird zurückgegeben, wenn die Liste leer ist.

Beispiele:

_.max(list, [iteratee], [context]);

-

    var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];

    var test = _.max(stooges, function(stooge)
    {
        return stooge.age
    });

    console.dir(test);

Funktion min

Returns the minimum value in list. If an iteratee function is provided, it will be used on each value to generate the criterion by which the value is ranked. Infinity is returned if list is empty, so an isEmpty guard may be required.

Beispiele:

_.min(list, [iteratee], [context]);

-

var numbers = [10, 5, 100, 2, 1000];

var test = _.min(numbers);

console.log(test);

Funktion sortBy

Returns a (stably) sorted copy of list, ranked in ascending order by the results of running each value through iteratee. iteratee may also be the string name of the property to sort by (eg. length).

Gibt eine sortiert Liste aufsteigender Reihenfolge zurück. Die Ergebnisse der einzelnen Werte werden durch eine iteratee Funktion geändert. Iteratee kann auch nach String Namen der Eigenschaft zu sortieren. Z.Bsp. nach der Länge.

Beispiele:

_.sortBy(list, iteratee, [context]);

-

var arr = [1, 2, 3, 4, 5, 6];

var test = _.sortBy(arr, function(num)
{
    var elem = Math.sin(num);

    console.log('gerechnet: ' + num + ' = ' + elem);

    return elem;
});

console.dir(test);

-

var arr = ['ccc','ddd','aaa','bbb','eee'];

var test = _.sortBy(arr);

console.dir(test);

Funktion groupBy

Splits a collection into sets, grouped by the result of running each value through iteratee. If iteratee is a string instead of a function, groups by the property named by iteratee on each of the values.

**

Beispiele:

_.groupBy(list, iteratee, [context]);

-

var arr = [1.3, 2.1, 2.4];

var test = _.groupBy(arr, function(num)
{
    return Math.floor(num);
});

console.dir(test);

-

var arr = [26.5, 26.2, 8, 17.9, 17.1, 23];

var test = _.groupBy(arr, function(num)
{
    return Math.floor(num);
});

console.dir(test);

Funktion indexBy

Given a list, and an iteratee function that returns a key for each element in the list (or a property name), returns an object with an index of each item. Just like groupBy, but for when you know your keys are unique.

Übersetzung

Beispiele:

_.indexBy(list, iteratee, [context]);

-

var personen = [        
    {name: 'larry', alter: 50},
    {name: 'moe', alter: 40},
    {name: 'curly', alter: 60}
];

var test = _.indexBy(personen, 'alter');

console.dir(test);

Funktion countBy

Sorts a list into groups and returns a count for the number of objects in each group. Similar to groupBy, but instead of returning a list of values, returns a count for the number of values in that group.

Sortiert eine Liste nach Gruppen und gibt die Anzahl der Elemente in jeder Gruppe zurück.

Beispiele:

_.countBy(list, iteratee, [context]);

-

var arr = [1, 2, 3, 4, 5];

var test = _.countBy(arr, function(num)
{
  return num % 2 == 0 ? 'even': 'odd';
});

console.dir(test);

Funktion shuffle

Returns a shuffled copy of the list, using a version of the Fisher-Yates shuffle.

Gibt eine willkürlich sortierte Liste zurück.

Beispiele:

_.shuffle([1, 2, 3, 4, 5, 6]);

Funktion sample

Produce a random sample from the list. Pass a number to return n random elements from the list. Otherwise a single random item will be returned.

Gibt eine willkürliche Liste aus der Liste der Anfangswerte zurück. Wird der zweite Parameter weggelassen, dann wird nur ein Element zurückgegeben.

Beispiele:

_.sample([1, 2, 3, 4, 5, 6]);

-

var arr = [1, 2, 3, 4, 5];

var test = _.sample(arr,3);

console.log(test);

Funktion toArray

Creates a real Array from the list (anything that can be iterated over). Useful for transmuting the arguments object.

Erstellt aus den Argumenten ein Array.

Beispiele:

_.toArray(list);

-

 var test = (function()
{
    return _.toArray(arguments).slice(2);
}
)(1, 2, 3, 4);

console.log(test);

Funktion size

Return the number of values in the list.

Gibt die Anzahl der Elemente in einer Liste zurück.

Beispiele:

_.size(list);

-

var obj = {
    einz: 1,
    zwei: 2,
    drei: 3,
    vier: 4
}

var test = _.size(obj);

console.log(test);

Funktion partition

Split array into two arrays: one whose elements all satisfy predicate and one whose elements all do not satisfy predicate.

**

Beispiele:

_.partition(array, predicate);

-

function isEven(n) {
  n = Number(n);
  return n === 0 || !!(n && !(n%2));
}

function isOdd(n) {
  return isEven(Number(n) + 1);
}

var arr = [0, 1, 2, 3, 4, 5];

var test = _.partition(arr, isOdd);

console.log(test);

2. Erkunden der Korrelation mit dem Data Explorer

Streuungsdiagramme sind graphische Hilfsmittel, die die Anordnung von Beobachtungspunkten vermitteln.Durch eine visuelle Kontrolle eines Streuungsdiagrammes kann ein Zusammenhang zwischen den Werten eines Streuungsdiagrammes vermutet werden. Es kann eine Schätzung der Gewichtung und die Art der Abhängigkeit vermutet werden. Bei wenigen Beobachtungspunkten ist das Streuungsdiagramm eine wertvolle Hilfe. Bei großen Datenmengen und einer Vielzahl von Parametern versagt jedoch diese Methode. Daher ist die Korrelation in diesem Fall zu verwenden.

In diesem Videotutorial wird die Verwendung des Data Explorer zur Bestimmung der Korrelation beschrieben.

Datensätze der verkauften TV's in den Filialen.

1. Start des Data Explorer

Die Verwendung des Programmes Data Explorer zur visuellen Datenanalyse.
Im ersten Videotutorial zum Programm Data Explorer beschäftigen wir uns mit der Installation
und den Möglichkeiten dieses Programm zu starten.

Videotutorial:

Funktionen der Javascript Bibliothek 'async.js'

Funktionen zur Nutzung von Kollektionen

  • each, eachSeries, eachLimit
    • Applies the function iteratee to each item in coll, in parallel
  • forEachOf, forEachOfSeries, forEachOfLimit
    • Like each, except that it passes the key (or index) as the second argument to the iteratee.
  • map, mapSeries, mapLimit
    • Produces a new collection of values by mapping each value in coll through the iteratee function.
  • filter, filterSeries, filterLimit
    • Returns a new array of all the values in coll which pass an async truth test.
  • reject, rejectSeries, rejectLimit
    • The opposite of filter. Removes values that pass an async truth test.
  • reduce
    • Reduces coll into a single value using an async iteratee to return each successive step.
  • reduceRight
    • Same as reduce, only operates on coll in reverse order.
  • detect, detectSeries, detectLimit
    • Returns the first value in coll that passes an async truth test.
  • sortBy
    • Sorts a list by the results of running each coll value through an async iteratee.
  • some, someLimit, someSeries
    • Returns true if at least one element in the coll satisfies an async test.
  • every, everyLimit, everySeries
    • Returns true if every element in coll satisfies an async test.
  • concat, concatSeries
    • Applies iteratee to each item in coll, concatenating the results.

Kontrolle der Steuerung

  • series
    • Run the functions in the tasks collection in series, each one running once the previous function has completed.
  • parallel, parallelLimit
    • Run the tasks collection of functions in parallel, without waiting until the previous function has completed.
  • whilst
    • Repeatedly call fn, while test returns true.
  • doWhilst
    • The post-check version of whilst. To reflect the difference in the order of operations, the arguments test and fn are switched.
  • until
    • Repeatedly call fn until test returns true.
  • doUntil
    • Like doWhilst, except the test is inverted.
  • during
    • Like whilst, except the test is an asynchronous function that is passed a callback in the form of function (err, truth)
  • doDuring
    • The post-check version of during.
  • forever
    • Calls the asynchronous function fn with a callback parameter that allows it to call itself again, in series, indefinitely.
  • waterfall
    • Runs the tasks array of functions in series, each passing their results to the next in the array.
  • compose
    • Creates a function which is a composition of the passed asynchronous functions.
  • seq
    • Version of the compose function that is more natural to read.
  • applyEach, applyEachSeries
    • Applies the provided arguments to each function in the array, calling callback after all functions have completed.
  • queue
    • Creates a queue object with the specified concurrency.
  • priorityQueue
    • The same as queue only tasks are assigned a priority and completed in ascending priority order.
  • cargo
    • Creates a cargo object with the specified payload.
  • auto
    • Determines the best order for running the functions in tasks, based on their requirements.
  • autoInject
    • A dependency-injected version of the auto function.
  • retry
    • Attempts to get a successful response from task no more than times times before returning an error.
  • retryable
    • A close relative of retry.
  • iterator
    • Creates an iterator function which calls the next function in the tasks
  • times, timesSeries, timesLimit
    • Calls the iteratee function n times, and accumulates results in the same manner you would use with map.
  • race
    • Runs the tasks array of functions in parallel, without waiting until the previous function has completed.

Werkzeuge

  • apply
    • Creates a continuation function with some arguments already applied.
  • nextTick
    • Calls callback on a later loop around the event loop.
  • memoize
    • Caches the results of an async function.
  • unmemoize
    • Undoes a memoized function, reverting it to the original, unmemoized form.
  • ensureAsync
    • Wrap an async function and ensure it calls its callback on a later tick of the event loop.
  • constant
    • Returns a function that when called, calls-back with the values provided.
  • asyncify
    • Take a sync function and make it async, passing its return value to a callback.
  • wrapSync
  • log
    • Logs the result of an async function to the console.
  • dir
    • Logs the result of an async function to the console using console.dir to display the properties of the resulting object.
  • noConflict
    • Changes the value of async back to its original value, returning a reference to the async object.
  • timeout
    • Sets a time limit on an asynchronous function.

Javascript Bibliothek underscore.js (Vers.: 1.8.3), Dokumentation (befindet sich in permanenter Überarbeitung)

Bearbeitung von Arrays

Funktion function

description

german translate

Alias: bla, blub

Beispiele:

Javascript Bibliothek underscore.js, Dokumentation (befindet sich in permanenter Überarbeitung)

underscore.js und asynchrone Abarbeitung von Funktionen

  // callback Funktion
function callback(text)
{
    return function(next)
    {
        // Ajax simulieren
        setTimeout(function()
        {
            console.log(text);
            next();
        },
        1000);
    }
}

// Liste mit Callback Funktionen
var actions = [ callback(1), callback(2), callback(3), callback(4), callback(5), callback(6) ]

// ruft die Funktionen entsprechend des Array
_(actions).reduceRight(_.wrap, function()
{
    console.warn('fertig');
})();

Verwendung des context in underscore Javascript

var person = {
    alter: []
};

var arr = [17, 19, 23];

var test = _.map(arr, function(num)
{
    this.alter.push(num);

    return num + 10;
}, person);

// Inhalt der bearbeiteten Werte
console.dir(test);

// Inhalt des Context
console.dir(person);

Die Phasen des Data Mining im Team

Innerhalb kürzester Zeit verdoppeln sich die Datenmengen.
Jedes Unternehmen und jede öffentliche Institution sammelt Daten.

War vor kurzem das sammeln und das auswerten dieser Daten nur größeren Firmen vorbehalten, so hat sich zum heutigen Zeitpunkt die Situation grundlegend gewandelt. In immer mehr Firmen reift die Erkenntnis, daß die Auswertung vorhandenen Daten einen Vorteil für das Unternehmen bedeutet.
Dank der Weiterentwicklung der Software und vorhandener Spezialisten sind diese Daten auch für kleinere Firmen nutzbar. Im wesentlichen sind zur Aufbereitung dieser Daten in einer Firma folgende Voraussetzungen zu schaffen.

Vorüberlegungen ( product owner )

  • zur Auswertung der Daten muss ein qualifiziertes Team zur Verfügung stehen
  • dieses Team muss aktiv in die Entscheidungsprozesse der Firma eingebunden werden
  • das Team hat eine Software ( Internet - Plattform ) um allen Entscheidungsträgern die aktuellen Ergebnisse zeitnah zu übermitteln
  • das Team kann auf eine zentrale Datenhaltung zurückgreifen in der die Geschäftsprozesse gespeichert sind
  • die Arbeit im Team wird agil ( Scrum / Kanban ) organisiert um auf sich verändernde Anforderungen reagieren zu können

Ausgehend von diesen Forderungen ist das Data - Mining der erste Schritt um Möglichkeiten, resultierend aus den vorhandenen Daten, zu erkennen.

Der Prozess des Data Mining wird in folgende Schritte unterteilt:

1. Analyse der zur Verfügung gestellten Daten ( data engineer )

  • es werden die verfügbaren Daten gesichtet
  • es wird erkundet welche Daten zur Verfügung stehen und ob diese Daten eine Analyse entsprechend der Kundenforderung ermöglicht
  • die Daten werden in eine Datenbank (MySQL) gespeichert
  • es wird die Datenstruktur erkundet
  • die Datenstruktur wird mit geeigneter Software visualisiert
    • Es wird in einer Darstellung die Relationen der neu geschaffenen Datenbank dokumentiert
    • eine andere Darstellung beschäftigt sich mit dem konkreten Aufbau der Tabellen dieser Datenbank
      • diese Tabellenstruktur kann in Listenform dargestellt werden
      • siehe dieses Tabellenschema
      • es empfiehlt sich für die Benennung der Tabellen und Spalten der neuen Datenbank eine Namenskonvention zu verwenden
      • Beispiel einer Namenskonvention
      • die Namenskonvention wird den Entwickler in einem Wiki zugänglich gemacht
  • Entsprechen die Daten nicht der Aufgabenstellung, so muß die Aufgabenstellung überarbeitet werden.
  • Den Projektteilnehmern muss klar sein, daß die Datenübermittlung und die Klärung von Fragen zur Datenstruktur, ein Prozess ist, für den bewusst Zeit zur Verfügung gestellt werden muss.
  • Offenen Fragen müssen durch den Datenlieferanten geklärt werden. Dazu ist die Zusammenarbeit mit einem Ansprechpartner durch den product owner zu organisieren.

2. Datenvorverarbeitung ( data engineer )

In der Vorverarbeitung wird die Qualität der Daten überprüft. Im allgemeinen wird davon ausgegangen das ein Teil der Daten für eine weitere Verarbeitung unbrauchbar ist. Diese unbrauchbaren Daten müssen entfernt werden. Allgemein wird gesagt das ca. 5% der Daten entfern werden müssen. Da sich unsere Daten bereits in einer Datenbank befinden können 2 Möglichkeiten zur Kontrolle verwandt werden.

  • Durch geeignete Fragestellungen in der Datenbank können 'Ausreisser' erkannt und beseitigt werden
  • zum zweiten können Daten der Datenbank visualisiert werden. Die Verwendung eines Datenbank - Client der größere Datenmengen in Diagrammform visualisiert ist sinnvoll. Leider unterstützen momentan vorhandene MySQL - Client - Programme diese Visualisierung nur ungenügend. Eine sinnvolle Lösung ist die Koppelung eines Client - Programmes mit einer statistischen Software. An geigneter Stelle wird dieses Verfahren beschrieben.

3. Datentransformation ( data engineer )

Die verfügbaren Rohdaten sind oftmals in ihrer Ursprungsform ungeeignet für das Data Mining. In der der Transformationsphase werden die Daten in eine Datenbank transformiert. Dabei können neue Attribute in den Datensätzen generiert werden. Entsprechend der Normalsierungsformen können die Daten auf mehrere Tabellen verteilt werden. Entsprechend der vorhandenen Data Mining Programmen werden die Daten vorbereitet.

4. Data Mining ( data scientist und data engineer )

Liegen die Datensätze in akzeptabler Qualität vor, kann eine Analyse durchgeführt werden. Es erfolgt eine Vorauswahl und eine Erkundung auf vorhandene Muster. Dafür verwenden wir unter anderem das Programm Dat Explorer.

Verwendung statistischen Software I
Verwendung statistischen Software II

5. Aufbau eines Rechenmodell ( data scientist )

6. Darstellung der Ergebnisse in einer Internet - Plattform ( data engineer und data scientist )

Mittelwerte

arithmetisches Mittel

\[\bar{x} = \frac{x_1 + x_2 + \ldots + x_n}{n} = \frac{1}{n} \cdot \sum_{i=1}^{n} x_i\]

Das bekannteste Lagemaß ist das arithmetische Mittel.Das arithmetische Mittel erhält man, in dem man alle Werte einer Liste aufsummiert und diese Summe durch die Anzahl der Elemente der Liste teilt.

Als Formel wird das arithmetische Mittel wie folgt ausgedrückt.

Glücklicherweise hat MySQL zur Lösung dieser Aufgabe eine Funktion. Diese ist die Funktion avg();

Mit dieser Funktion können wir das arithmetische Mittel der Löhne in unserer 'personen' Tabelle berechnen.

SELECT AVG(t.lohn) AS mittelwert FROM personen t;

Eine weitere Möglichkeit ist das direkte umsetzen der oben aufgeführten Formel.

SELECT SUM( t.lohn ) / COUNT( t.lohn ) AS mittelwert FROM personen t

Das Ergebnis ist 3805,32 €

geometrisches Mittel

\[\bar{x}_{\text{geom}} = \sqrt[n]{x_1 \cdot x_2 \cdot \ldots \cdot x_n} = \sqrt[n]{\prod_{i=1}^n x_i}\]

Das geometrische Mittel wird im Zusammenhang mit Wachstums und Zinsfaktoren berechnet. Berechnet wird das geometrische Mittel indem alle Faktoren miteinander multipliziert und daraus dann die n-te Wurzel gezogen wird.

Machen wir uns das geometrische Mittel mit einem Beispiel klar. Nachfolgend ein erfundenes Beispiel für das Wachstum eines Betriebes im Zeitraum von 1981 bis 1991.

jahr wachstumsrate wachstumsfaktor
1981 -2.39 0.9761
1982 -1.93 0.9807
1983 -1.77 0.9823
1984 -1.35 0.9865
1985 -0.81 0.9919
1986 0.32 1.0032
1987 0.10 1.0010
1988 0.43 1.0043
1989 3.87 1.0387
1990 4.03 1.0403
1991 1.15 1.0115

Das geometrische Mittel kann für unser Beispiel in MySQL wie folgt berechnet werden.

SELECT POW( EXP( SUM( LOG( t.wachstumsfaktor ) ) ), 1 / COUNT( t.wachstumsfaktor ) )  AS wachstum FROM geometrisches t

eine zweite Möglichkeit ist

SELECT EXP( SUM( LOG( t.wachstumsfaktor ) ) / COUNT( t.wachstumsfaktor ) ) AS wachstum FROM geometrisches t

Das Ergebnis ist 1.0012

harmonisches Mittel

\[\bar{x}_{\text{harm}} = \frac{s_1 + \ldots + s_n}{\frac{s_1}{v_1} + \ldots + \frac{s_n}{v_n}} = \frac{\sum_{i = 1}^{n} s_i }{\frac{\sum_{i = 1}^{n} s_i}{\sum_{i = 1}^{n} v_i}}\]

Das harmonische Mittel kann sinnvoll sein wenn es um die Ermittlung einer durchschnittlichen Geschwindigkeit geht. Auch hierzu ein Beispiel. Wir haben ein Fahrzeug welches auf unterschiedlichen Strassen unterwegs ist. In der nachfolgenden Tabelle wird der Strassentyp, die gefahrene Strecke auf dieser Strasse und die Geschwindigkeit dargestellt.

strasse strecke km geschwindigkeit km/h
autobahn 100 150
landstrasse 90 70
stadt 75 40
SELECT SUM(strecke) / SUM(strecke / geschwindigkeit) AS geschwindigkeit FROM harmonisch

Das Ergebnis ist 69.23

Berechnung der Abweichungen in einer Liste

Berechnung der Abweichungen

STDDEV_POP( x ) = STD( x ) = STDDEV( x )

VAR_POP( x ) = VARIANCE( x )

VAR_POP( x ) = STDDEV_POP( x ) * STDDEV_POP( x )

VAR_POP( x ) = VAR_SAMP( x ) *( COUNT( x ) - 1 ) / COUNT( x )

VAR_POP( x ) = SUM( x x ) / COUNT( x ) - AVG( x ) AVG( x )

VAR_SAMP( x ) = STDDEV_SAMP( x ) * STDDEV_SAMP( x )

VAR_SAMP( x ) = VAR_POP( x ) /( COUNT( x ) - 1 ) * COUNT( x )

Boxplot

Der Boxplot ist ein Diagramm, das zur grafischen Darstellung der Verteilungvon Daten verwendet wird.
Es fasst verschiedene Lagemaße in einer Darstellung zusammen und dient der schnellen Übersicht der Streuung der Daten.

id vorname name geschlecht lohn
2 Patricia Holmes w 300
6 Earl Allen m 800
8 Wanda Ward w 800
5 Bruce Gilbert m 900
1 Anna Adams w 1200
9 Eric Welch m 1300
7 Charles Medina m 1400
3 Nicholas Matthews m 1600
4 Lisa Jackson w 2000
SELECT 
  (SELECT 
    FLOOR(COUNT(*) / 4) 
  FROM
    mittelwert) AS erste_quantil,
  (SELECT 
    FLOOR(COUNT(*) / 2) 
  FROM
    mittelwert) AS mid_pos,
  (SELECT 
    FLOOR(COUNT(*) / 4 * 3) 
  FROM
    mittelwert) AS dritte_quantil 
FROM
  mittelwert 
ORDER BY lohn LIMIT 1;
erste_quantil mid_pos dritte_quantil
2 4 6
SELECT 
  MIN(lohn),
  (SELECT 
    lohn
  FROM
    mittelwert
  ORDER BY lohn
  LIMIT 2, 1) AS firstq,
  (SELECT 
    lohn
  FROM
    mittelwert 
  ORDER BY lohn
  LIMIT 4, 1) AS median,
  (SELECT 
    lohn 
  FROM
    mittelwert
  ORDER BY lohn
  LIMIT 6, 1) AS last_q,
  MAX(lohn) 
FROM
  mittelwert ;
min(lohn) firstq median last_q max(lohn)
300 800 1200 1400 2000

Ergebnis

Verwendung der Lageregeln

Für metrisch skalierte Werte können das 'arithmetische Mittel', der 'Median' und der 'Modus' verwendet werden um die Symetrie oder Schiefe der Verteilung in einer Liste zu beurteilen.

Folgende Lageregeln existieren

  • symetrische Verteilung:

    \[\bar{x} \approx x_{med} \approx x_{mod}\]

  • linkssteile Verteilung:

    \[\bar{x} > x_{med} > x_{mod}\]

  • rechtssteile Verteilung:

    \[\bar{x} < x_{med} < x_{mod}\]

Beispiele für die Verteilung

element liste1 liste2 liste3
1 8 1 1
2 10 2 2
3 8 4 2
4 6 8 4
5 5 10 5
6 4 8 6
7 2 4 8
8 2 2 10
9 1 1 8
Summe 48 40 46
x arithm 5.11 4.44 5.11
x med 5 4 5
x mod 2 1 2

Grafik linkssteile Verteilung

Grafik symetrische Verteilung

Grafik rechtssteile Verteilung

Statistische Kenngrößen

Für die Beispiele verwende ich die Daten der nachfolgenden Tabelle

id vorname name geschlecht lohn
1 Anna Adams w 1200
2 Patricia Holmes w NULL
3 Nicholas Matthews m 1600
4 Lisa Jackson w 2000
5 Bruce Gilbert m 900
6 Earl Allen m 800
7 Charles Medina m 1400
8 Wanda Ward w 800
9 Eric Welch m 1300
10 Mildred Stanley w NULL

Berechnung des Mittelwertes des Lohnes

Als erstes wird die Summe der Lohnzahlungen errechnet.

SELECT SUM(t.lohn) FROM mittelwert t

Das Ergebnis ist 10000 €

Die Berechnung des arithmetischen Mittelwertes ist relativ simpel und kann in MySQL schnell durchgeführt werden.

SELECT AVG(t.lohn) FROM mittelwert t

Für unser Beispiel ist das 1250 € !!! Um diesen Fehler zu korrigieren muss das arithmetische Mittel wie folgt berechnet werden.

SELECT AVG(COALESCE(t.lohn,0)) AS mittelwert FROM mittelwert t

Berechnung des Mittelwertes der Löhne gruppiert nach Geschlecht

SELECT NAME, AVG(COALESCE(t.lohn,0)) AS mittelwert FROM mittelwert t GROUP BY geschlecht;

Das Ergebnis ist

geschlecht mittelwert
m 1200
w 800

Berechnung des Modalwertes

Der Modalwert gibt den häufigsten Wert in einer Liste wieder.

\(\bar{x}_{\text{d}} = \text{Häufigster Beobachtungswert}\)

Zum berechnen des Modalwertes verwende ich folgende Query.

SELECT lohn, COUNT( * ) AS anzahl
FROM mittelwert
GROUP BY lohn
ORDER BY COUNT( * ) DESC
LIMIT 1;

In unserem Beispiel ist 'NULL' der Modalwert

Berechnung des Median / Zentralwert

Der Median entspricht dem Wert in einer Liste, welcher größer oder gleich 50% aller Werte der Liste ist.
Es muss beachtet werden dass die Berechnung in einer Liste mit einer geraden Anzahl von Elementen
anders ist als in einer Liste mit einer ungeraden Anzahl von Elementen.

\(\begin{equation*}
\tilde{x} = \begin{cases}
x_{\frac{n+1}{2}} & \text{für } n \text{ ungerade}\\
\frac{1}{2}\left(x_{\frac{n}{2}} + x_{\frac{n}{2}+1}\right) & \text{für } n \text{ gerade}
\end{cases}
\end{equation*}\)

Hier die Lösung

SELECT x.lohn FROM mittelwert X, mittelwert Y
GROUP BY x.lohn
HAVING SUM(SIGN(1-SIGN(y.lohn-x.lohn)))/COUNT(*) > .5
LIMIT 1;

Das Ergebnis

lohn
1200

Mittelwerte

arithmetisches Mittel

\[\bar{x} = \frac{x_1 + x_2 + \ldots + x_n}{n} = \frac{1}{n} \cdot \sum_{i=1}^{n} x_i\]

Das bekannteste Lagemaß ist das arithmetische Mittel.Das arithmetische Mittel erhält man, in dem man alle Werte einer Liste aufsummiert und diese Summe durch die Anzahl der Elemente der Liste teilt.

Als Formel wird das arithmetische Mittel wie folgt ausgedrückt.

Glücklicherweise hat MySQL zur Lösung dieser Aufgabe eine Funktion. Diese ist die Funktion avg();

Mit dieser Funktion können wir das arithmetische Mittel der Löhne in unserer 'personen' Tabelle berechnen.

SELECT AVG(t.lohn) AS mittelwert FROM personen t;

Eine weitere Möglichkeit ist das direkte umsetzen der oben aufgeführten Formel.

SELECT SUM( t.lohn ) / COUNT( t.lohn ) AS mittelwert FROM personen t

Das Ergebnis ist 3805,32 €

geometrisches Mittel

\[\bar{x}_{\text{geom}} = \sqrt[n]{x_1 \cdot x_2 \cdot \ldots \cdot x_n} = \sqrt[n]{\prod_{i=1}^n x_i}\]

Das geometrische Mittel wird im Zusammenhang mit Wachstums und Zinsfaktoren berechnet. Berechnet wird das geometrische Mittel indem alle Faktoren miteinander multipliziert und daraus dann die n-te Wurzel gezogen wird.

Machen wir uns das geometrische Mittel mit einem Beispiel klar. Nachfolgend ein erfundenes Beispiel für das Wachstum eines Betriebes im Zeitraum von 1981 bis 1991.

jahr wachstumsrate wachstumsfaktor
1981 -2.39 0.9761
1982 -1.93 0.9807
1983 -1.77 0.9823
1984 -1.35 0.9865
1985 -0.81 0.9919
1986 0.32 1.0032
1987 0.10 1.0010
1988 0.43 1.0043
1989 3.87 1.0387
1990 4.03 1.0403
1991 1.15 1.0115

Das geometrische Mittel kann für unser Beispiel in MySQL wie folgt berechnet werden.

SELECT POW( EXP( SUM( LOG( t.wachstumsfaktor ) ) ), 1 / COUNT( t.wachstumsfaktor ) )  AS wachstum FROM geometrisches t

eine zweite Möglichkeit ist

SELECT EXP( SUM( LOG( t.wachstumsfaktor ) ) / COUNT( t.wachstumsfaktor ) ) AS wachstum FROM geometrisches t

Das Ergebnis ist 1.0012

harmonisches Mittel

\[\bar{x}_{\text{harm}} = \frac{s_1 + \ldots + s_n}{\frac{s_1}{v_1} + \ldots + \frac{s_n}{v_n}} = \frac{\sum_{i = 1}^{n} s_i }{\frac{\sum_{i = 1}^{n} s_i}{\sum_{i = 1}^{n} v_i}}\]

Das harmonische Mittel kann sinnvoll sein wenn es um die Ermittlung einer durchschnittlichen Geschwindigkeit geht. Auch hierzu ein Beispiel. Wir haben ein Fahrzeug welches auf unterschiedlichen Strassen unterwegs ist. In der nachfolgenden Tabelle wird der Strassentyp, die gefahrene Strecke auf dieser Strasse und die Geschwindigkeit dargestellt.

strasse strecke km geschwindigkeit km/h
autobahn 100 150
landstrasse 90 70
stadt 75 40
SELECT SUM(strecke) / SUM(strecke / geschwindigkeit) AS geschwindigkeit FROM harmonisch

Das Ergebnis ist 69.23