vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Blitzschnelles Erstellen von grafischen Diagrammen!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Variablen/Strings · Algorithmen/Mathematik   |   VB-Versionen: VB2008, VB201030.01.13
Rang-Transformation von Messreihen

Ein Modul mit verschiedenen Verfahren zur Umwandlung einer Datenreihe in Ränge.

Autor:   Manfred BohnBewertung:     [ Jetzt bewerten ]Views:  7.164 
ohne HomepageSystem:  WinXP, Win7, Win8, Win10, Win11kein Beispielprojekt 

Zur Bestimmung einer äquidistanten Rangreihe zu einer Liste von Messungen wird diese Liste zunächst sortiert und die Ränge werden anhand der Sortier-Position der Messwerte zugeordnet.

Bei der Umwandlung einer Liste von Messwerten in eine Rangreihe geht die Information über die Abstände zwischen den Ausprägungen verloren. (Extreme Messungen werden dabei "eingefangen", ungünstige mehrgipflige, schiefe] Messwert-Verteilungen verschwinden.)

Die Funktion "RankOrder" erwartet als ersten Parameter ("data") eine Liste von (unsortierten) Messungen und gibt eine Liste der zugeordneten Rangwerte (Datentyp: "Double") zurück. Falls die Funktion scheitert, wird "Nothing" zurückgegeben (z.B. bei der Übergabe von ungeeigneten Parametern).

Es gibt eine Überladung, die als Datentyp der Werteliste beliebige Strukturen akzeptiert, falls die Schnittstelle "IConvertible" (für die Zuordnung eines Double-Wertes) implementiert ist.
Das Sortieren der Liste erfolgt in allen Fällen durch den Standard-Comparer für Double-Werte. (Die Liste darf keine "Double.NaN"-Werte enthalten.) Falls Gleitkommawerte transformiert werden, ist eventuell eine geeignete Vorverarbeitung erforderlich, um zu steuern, welche Wert-Differenzen noch als "gleich" einzustufen sind (z.B. Rundung).

Durch optionale Parameter kann die Art der Rang-Zuordnung gesteuert werden:

Parameter: SortOrder
Bei "Ascending" werden die Daten intern ansteigend sortiert. Dem relativ kleinsten Wert wird der niedrigste Rang zugeordnet. Bei "Descending" werden die Daten fallend sortiert, d.h. dem relativ größten Wert wird der niedrigste Rang zugeordnet.

Parameter: RankBindingMethod
Dieser Parameter ist nur von Bedeutung, wenn in der Datenreihe Wert-Ausprägungen mehrfach vorkommen. In dem Fall ist die Rangreihe nicht eindeutig definierbar. Es sind verschiedene Optionen möglich:

Bei "Low" ("High") wird den ausprägungs-gleichen Werten der jeweils niedrigste (höchste) der möglichen Rangwerte zugeordnet.
Beispiel 1, 2, 3, 3, 3, 3, 4, 5 --> 1, 2, 3, 3, 3, 3, 7, 8 (Low) 1, 2, 6, 6, 6, 6, 7, 8 (High)

Bei "Mean" wird den ausprägungs-gleichen Werten die mittlere Ausprägung der möglichen Rangwerte zugeordnet. Diese Variante wird meist bei statistischen Analysen eingesetzt.
Beispiel: 1, 2, 3, 3, 3, 3, 4, 5 --> 1, 2, 4.5, 4.5, 4.5, 4.5, 7, 8

Bei "Random" wird den ausprägungs-gleichen Werten per Zufall jeweils einer der möglichen Rangwerte zugeordnet. Weil dabei Rang-Unterschiede erzeugt werden, für die es in der Datenreihe keine Entsprechung gibt, ist dieses Verfahren nur geeignet, wenn die Zahl der Rangbindungen gering ist.
Beispiel: 1, 2, 3, 3, 3, 3, 4, 5 --> 1, 2, 5, 3, 4, 6, 7, 8

Parameter: FirstRankValue / RankDifference
Der Parameter "FirstRankValue" legt fest, welcher numerische Wert dem kleinsten Rang entspricht. Die folgenden Positionen in der Rangreihe werden durch Rückgriff auf die Angabe in "RankDifference" gebildet. Dieser Parameter muß größer als 0 gewählt werden und bestimmt die Differenz zwischen den aufeinanderfolgenden Rängen.

Rückgabe-Parameter: DistinctValues
In "DistinctValues" wird gemeldet, wie viele unterscheidbare Werte in der übergebenen Liste enthalten sind.

Hinweis:
Die Funktion "RankOrder" verwendet Methoden des Objekts "System.Collections.Generic.List(Of T)".
Für die Bearbeitung sehr langer Listen (ab ca. 1000 Elementen) ist eine Implementierung zu empfehlen, die beim Sortieren der Daten einen Zeiger auf die Position in der unsortierten Liste liefert (statt der Verwendung von "IndexOf").

Option Strict On
Option Explicit On
Option Infer Off
 
Imports System
Imports System.Collections.Generic ' List
Imports System.Windows.Forms ' SortOrder
Imports System.Linq ' Distinct
 
 
Module modRank
 
  ''' <summary>Verfahren der Rangzuweisung bei gleichen Werten</summary>
  Public Enum RankbindingMethod
    ''' <summary>Der kleinste der möglichen Ränge wird zugewiesen</summary>
    Low
    ''' <summary>Der größte der möglichen Ränge wird zugewiesen</summary>
    High
    ''' <summary>Der mittlere der möglichen Ränge wird zugewiesen</summary>
    Mean
    ''' <summary>Ein zufälliger Rang aus den möglichen Rängen wird zugewiesen</summary>
    Random
  End Enum
 
  ''' <summary>Erstellen einer Rangreihe aus einer Liste von Messwerten</summary>
  ''' <param name="data">Liste der Messwerte</param>
  ''' <param name="SortOrder">Sortierrichtung (Ascending: dem kleinsten Messwert
  ''' <param name="RankBindingMethod">Methode zur Behandlung von Messwerten mit 
  '''  gleicher Ausprägung</param>
  ''' wird der niedrigste Rang zugeordnet, sonst: der höchste Rang)</param>
  ''' <param name="FirstRankValue">Ausprägung des niedrigsten Rangs</param>
  ''' <param name="RankDifference">Differenz zwischen zwei 
  ''' aufeinanderfolgenden Rängen (positiver Wert)</param>
  ''' <param name="DistinctValues">Anzahl unterscheidbarer Ausprägungen</param>
  ''' <returns>Liste der zugeordneten Ränge (oder Nothing)</returns>
  Public Function RankOrder(Of T As {Structure, IConvertible}) ( _
    ByVal data As List(Of T), _
    Optional ByVal SortOrder As SortOrder = SortOrder.Ascending, _
    Optional ByVal RankBindingMethod As RankbindingMethod = RankbindingMethod.Mean, _
    Optional ByVal FirstRankValue As Double = 1.0#, _
    Optional ByVal RankDifference As Double = 1.0#, _
    Optional ByRef DistinctValues As Integer = -1) As List(Of Double)
 
    Try
 
      Dim dbl As New List(Of Double)
      ' Umwandlung der Daten in Double-Werte
      For i As Integer = 0 To data.Count - 1
        dbl.Add(CType(Convert.ChangeType(data(i), GetType(Double)), Double))
      Next i
 
      Return RankOrder(dbl, SortOrder, RankBindingMethod, _
        FirstRankValue, RankDifference, DistinctValues)
 
    Catch ex As Exception
      Return Nothing
    End Try
 
  End Function
 
  ''' <summary>Erstellen einer Rangreihe aus einer Liste von Messwerten</summary>
  ''' <param name="data">Liste der Messwerte</param>
  ''' <param name="SortOrder">Sortierrichtung (Ascending: dem kleinsten Messwert
  ''' wird der niedrigste Rang zugeordnet, sonst: der höchste Rang)</param>
  ''' <param name="RankBindingMethod">Methode zur Behandlung von Messwerten mit 
  '''  gleicher Ausprägung</param>
  ''' <param name="FirstRankValue">Ausprägung des niedrigsten Rangs</param>
  ''' <param name="RankDifference">Differenz zwischen zwei 
  ''' aufeinanderfolgenden Rängen (positiver Wert)</param>
  ''' <param name="DistinctValues">Anzahl unterscheidbarer Ausprägungen</param>
  ''' <returns>Liste der zugeordneten Ränge (oder Nothing)</returns>
  Public Function RankOrder(ByVal data As List(Of Double), _
    Optional ByVal SortOrder As SortOrder = SortOrder.Ascending, _
    Optional ByVal RankBindingMethod As RankbindingMethod = RankbindingMethod.Mean, _
    Optional ByVal FirstRankValue As Double = 1.0#, _
    Optional ByVal RankDifference As Double = 1.0#, _
    Optional ByRef DistinctValues As Integer = -1) As List(Of Double)
 
    ' Parameter-Werte überprüfen
    If data Is Nothing OrElse data.Count = 0 Then Return Nothing
    If Not data.IndexOf(Double.NaN) = -1 Then Return Nothing
 
    ' Sind FirstRankValue und RankDifference numerisch sinnvoll?
    If Double.IsNaN(FirstRankValue) Then Return Nothing
    If Double.IsNaN(RankDifference) Then Return Nothing
    If FirstRankValue >= FirstRankValue + RankDifference Then
      Return Nothing
    End If
    If FirstRankValue + (data.Count - 1) * RankDifference >= _
      FirstRankValue + data.Count * RankDifference Then
      Return Nothing
    End If
 
    Try
      ' Kopieren der Liste für internen Gebrauch (Markierung)
      Dim idata As New List(Of Double)(data)
 
      ' Werte sortieren
      Dim sortdata As New List(Of Double)(data)
      sortdata.Sort()
      If SortOrder = SortOrder.Descending Then
        sortdata.Reverse()
      End If
 
      Dim firstindex, lastindex, dataindex As Integer ' für Indizierungen
      Dim ranks(data.Count - 1), rank, rankvalue As Double ' für Rangzuordnungen
      ' für Zufallszuordnung von Rängen bei gleichen Messwerten (Rangbindung)
      Dim rankrandom As New List(Of Integer), rndm As New Random(Now.Millisecond)
 
      ' Schleife über die Liste der sortierten Werte
      firstindex = 0
      Do
        ' Indexbereich für ausprägungsgleiche Messwerte ermitteln
        lastindex = sortdata.LastIndexOf(sortdata(firstindex))
 
        If RankBindingMethod = modRank.RankbindingMethod.Random Then
          ' Rangpositionen für Zufallszuordnung im Indexbereich
          rankrandom.Clear()
          For i As Integer = 0 To lastindex - firstindex
            rankrandom.Add(firstindex + i)
          Next i
        End If
 
        ' Schleife über alle Messwerte mit gleicher Ausprägung
        For i As Integer = firstindex To lastindex
          ' Ermittlung der Rangposition anhand der vorgegebenen Methode
          Select Case RankBindingMethod
            Case RankBindingMethod.High : rank = lastindex
            Case RankBindingMethod.Low : rank = firstindex
            Case RankBindingMethod.Mean
              rank = (lastindex + firstindex) / 2
            Case RankBindingMethod.Random
              ' zufälligen Rang wählen (ohne Wiederholung)
              With rankrandom
                Dim rk As Integer = rndm.Next(0, .Count)
                rank = .Item(rk)
                .RemoveAt(rk)
              End With
          End Select
 
          ' Rangwert anhand der Parameter aus der Rangposition berechnen
          rankvalue = FirstRankValue + rank * RankDifference
 
          ' Zuordnung des Rangwertes auf die unsortierte Werte-Reihung
          dataindex = idata.IndexOf(sortdata(i))
          idata(dataindex) = Double.NaN ' Index als bearbeitet markieren
          ranks(dataindex) = rankvalue
        Next i
 
        firstindex = lastindex + 1
      Loop While firstindex < sortdata.Count ' Schleife über sortierte Messwerte
 
      DistinctValues = data.Distinct.Count() ' Anzahl unterscheidbarer Messwerte
      Return New List(Of Double)(ranks) ' Liste der zugeordneten Rangwerte
    Catch
      Return Nothing
    End Try
  End Function
 
End Module

Dieser Tipp wurde bereits 7.164 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel