Rubrik: Variablen/Strings · Algorithmen/Mathematik | VB-Versionen: VB2008, VB2010 | 30.01.13 |
Rang-Transformation von Messreihen Ein Modul mit verschiedenen Verfahren zur Umwandlung einer Datenreihe in Ränge. | ||
Autor: Manfred Bohn | Bewertung: | Views: 7.187 |
ohne Homepage | System: WinXP, Win7, Win8, Win10, Win11 | kein 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