Freigeben über


pairwise_dist_fl()

Gilt für: ✅Microsoft Fabric✅Azure Data Explorer

Berechnen Sie paarweise Abstände zwischen Entitäten basierend auf mehreren nominalen und numerischen Variablen.

Die Funktion pairwise_dist_fl() ist eine UDF (benutzerdefinierte Funktion), die den multivariaten Abstand zwischen datenpunkten berechnet, die derselben Partition angehören, wobei nominale und numerische Variablen berücksichtigt werden.

  • Alle Zeichenfolgenfelder, neben Entitäts- und Partitionsnamen, gelten als Nominalvariablen. Der Abstand ist gleich 1, wenn die Werte unterschiedlich sind, und 0, wenn sie identisch sind.
  • Alle numerischen Felder werden als numerische Variablen betrachtet. Sie werden normalisiert, indem sie in Z-Werte transformiert werden und der Abstand als absoluter Wert der Differenz berechnet wird. Der gesamt multivariate Abstand zwischen Datenpunkten wird als Mittelwert der Abstände zwischen Variablen berechnet.

Eine Entfernung nahe Null bedeutet, dass die Entitäten ähnlich sind und eine Entfernung über 1 bedeutet, dass sie unterschiedlich sind. Ebenso weist eine Entität mit einem mittleren Abstand nahe oder über einer Entität darauf hin, dass sie sich von vielen anderen Entitäten in der Partition unterscheidet und einen potenziellen Ausreißer angibt.

Die Ausgabe der Funktion ist paarweise Entfernungen zwischen Entitäten unter derselben Partition. Es kann verwendet werden, um nach ähnlichen oder unterschiedlichen Paaren zu suchen. z. B. Entitäten mit minimalen Abständen teilen viele gemeinsame Features. Sie kann auch einfach in eine Entfernungsmatrix transformiert werden (siehe Verwendungsbeispiel) oder als Eingabe für Clustering- oder Ausreißererkennungsalgorithmen verwendet werden.

Syntax

pairwise_dist_fl(Entität, Partition)

Erfahren Sie mehr über Syntaxkonventionen.

Parameter

Name Type Erforderlich Beschreibung
Entität string ✔️ Der Name der Eingabetabellenspalte, die die Namen oder IDs der Entitäten enthält, für die die Entfernungen berechnet werden.
partition string ✔️ Der Name der Eingabetabellenspalte, die die Partition oder den Bereich enthält, sodass die Abstände für alle Entitätenpaare unter derselben Partition berechnet werden.

Funktionsdefinition

Sie können die Funktion definieren, indem Sie den Code entweder als abfragedefinierte Funktion einbetten oder wie folgt als gespeicherte Funktion in Ihrer Datenbank erstellen:

Definieren Sie die Funktion mithilfe der folgenden Let-Anweisung. Es sind keine Berechtigungen erforderlich.

Wichtig

Eine Let-Anweisung kann nicht alleine ausgeführt werden. Auf sie muss eine tabellarische Ausdrucksanweisung folgen. Informationen zum Ausführen eines funktionierenden Beispiels pairwise_dist_fl()finden Sie unter Beispiel.

let pairwise_dist_fl = (tbl:(*), id_col:string, partition_col:string)
{
    let generic_dist = (value1:dynamic, value2:dynamic) 
    {
        // Calculates the distance between two values; treats all strings as nominal values and numbers as numerical,
        // can be extended to other data types or tweaked by adding weights or changing formulas.
            iff(gettype(value1[0]) == "string", todouble(tostring(value1[0]) != tostring(value2[0])), abs(todouble(value1[0]) - todouble(value2[0])))
    };
    let T = (tbl | extend _entity = column_ifexists(id_col, ''), _partition = column_ifexists(partition_col, '') | project-reorder _entity, _partition);
    let sum_data = (
        // Calculates summary statistics to be used for normalization.
        T
        | project-reorder _entity
        | project _partition, p = pack_array(*)
        | mv-expand with_itemindex=idx p
        | summarize count(), avg(todouble(p)), stdev(todouble(p)) by _partition, idx
        | sort by _partition, idx asc
        | summarize make_list(avg_p), make_list(stdev_p) by _partition
    );
    let normalized_data = (
        // Performs normalization on numerical variables by substrcting mean and scaling by standard deviation. Other normalization techniques can be used
        // by adding metrics to previous function and using here.
        T
        | project _partition, p = pack_array(*)
        | join kind = leftouter (sum_data) on _partition
        | mv-apply p, list_avg_p, list_stdev_p on (
            extend normalized = iff((not(isnan(todouble(list_avg_p))) and (list_stdev_p > 0)), pack_array((todouble(p) - todouble(list_avg_p))/todouble(list_stdev_p)), p)
            | summarize a = make_list(normalized) by _partition
        )
        | project _partition, a
    );
    let dist_data = (
        // Calculates distances of included variables and sums them up to get a multivariate distance between all entities under the same partition.
        normalized_data
        | join kind = inner (normalized_data) on _partition
        | project entity = tostring(a[0]), entity1 = tostring(a1[0]), a = array_slice(a, 1, -1), a1 = array_slice(a1, 1, -1), _partition
        | mv-apply a, a1 on 
        (
            project d = generic_dist(pack_array(a), pack_array(a1))
            | summarize d = make_list(d)
        )
        | extend dist = bin((1.0*array_sum(d)-1.0)/array_length(d), 0.0001) // -1 cancels the artifact distance calculated between entity names appearing in the bag and normalizes by number of features        
        | project-away d
        | where entity != entity1
        | sort by _partition asc, entity asc, dist asc
    );
    dist_data
};
// Write your query to use the function here.

Beispiel

Im folgenden Beispiel wird der Aufrufoperator verwendet, um die Funktion auszuführen.

Um eine abfragedefinierte Funktion zu verwenden, rufen Sie sie nach der definition der eingebetteten Funktion auf.

let pairwise_dist_fl = (tbl:(*), id_col:string, partition_col:string)
{
    let generic_dist = (value1:dynamic, value2:dynamic) 
    {
        // Calculates the distance between two values; treats all strings as nominal values and numbers as numerical,
        // can be extended to other data types or tweaked by adding weights or changing formulas.
            iff(gettype(value1[0]) == "string", todouble(tostring(value1[0]) != tostring(value2[0])), abs(todouble(value1[0]) - todouble(value2[0])))
    };
    let T = (tbl | extend _entity = column_ifexists(id_col, ''), _partition = column_ifexists(partition_col, '') | project-reorder _entity, _partition);
    let sum_data = (
        // Calculates summary statistics to be used for normalization.
        T
        | project-reorder _entity
        | project _partition, p = pack_array(*)
        | mv-expand with_itemindex=idx p
        | summarize count(), avg(todouble(p)), stdev(todouble(p)) by _partition, idx
        | sort by _partition, idx asc
        | summarize make_list(avg_p), make_list(stdev_p) by _partition
    );
    let normalized_data = (
        // Performs normalization on numerical variables by substrcting mean and scaling by standard deviation. Other normalization techniques can be used
        // by adding metrics to previous function and using here.
        T
        | project _partition, p = pack_array(*)
        | join kind = leftouter (sum_data) on _partition
        | mv-apply p, list_avg_p, list_stdev_p on (
            extend normalized = iff((not(isnan(todouble(list_avg_p))) and (list_stdev_p > 0)), pack_array((todouble(p) - todouble(list_avg_p))/todouble(list_stdev_p)), p)
            | summarize a = make_list(normalized) by _partition
        )
        | project _partition, a
    );
    let dist_data = (
        // Calculates distances of included variables and sums them up to get a multivariate distance between all entities under the same partition.
        normalized_data
        | join kind = inner (normalized_data) on _partition
        | project entity = tostring(a[0]), entity1 = tostring(a1[0]), a = array_slice(a, 1, -1), a1 = array_slice(a1, 1, -1), _partition
        | mv-apply a, a1 on 
        (
            project d = generic_dist(pack_array(a), pack_array(a1))
            | summarize d = make_list(d)
        )
        | extend dist = bin((1.0*array_sum(d)-1.0)/array_length(d), 0.0001) // -1 cancels the artifact distance calculated between entity names appearing in the bag and normalizes by number of features        
        | project-away d
        | where entity != entity1
        | sort by _partition asc, entity asc, dist asc
    );
    dist_data
};
//
let raw_data = datatable(name:string, gender: string, height:int, weight:int, limbs:int, accessory:string, type:string)[
    'Andy',     'M',    160,    80,     4,  'Hat',      'Person',
    'Betsy',    'F',    170,    70,     4,  'Bag',      'Person',
    'Cindy',    'F',    130,    30,     4,  'Hat',      'Person',
    'Dan',      'M',    190,    105,    4,  'Hat',      'Person',
    'Elmie',    'M',    110,    30,     4,  'Toy',      'Person',
    'Franny',   'F',    170,    65,     4,  'Bag',      'Person',
    'Godzilla', '?',    260,    210,    5,  'Tail',     'Person',
    'Hannie',   'F',    112,    28,     4,  'Toy',      'Person',
    'Ivie',     'F',    105,    20,     4,  'Toy',      'Person',
    'Johnnie',  'M',    107,    21,     4,  'Toy',      'Person',
    'Kyle',     'M',    175,    76,     4,  'Hat',      'Person',
    'Laura',    'F',    180,    70,     4,  'Bag',      'Person',
    'Mary',     'F',    160,    60,     4,  'Bag',      'Person',
    'Noah',     'M',    178,    90,     4,  'Hat',      'Person',
    'Odelia',   'F',    186,    76,     4,  'Bag',      'Person',
    'Paul',     'M',    158,    69,     4,  'Bag',      'Person',
    'Qui',      'F',    168,    62,     4,  'Bag',      'Person',
    'Ronnie',   'M',    108,    26,     4,  'Toy',      'Person',
    'Sonic',    'F',    52,     20,     6,  'Tail',     'Pet',
    'Tweety',   'F',    52,     20,     6,  'Tail',     'Pet' ,
    'Ulfie',    'M',    39,     29,     4,  'Wings',    'Pet',
    'Vinnie',   'F',    53,     22,     1,  'Tail',     'Pet',
    'Waldo',    'F',    51,     21,     4,  'Tail',     'Pet',
    'Xander',   'M',    50,     24,     4,  'Tail',     'Pet'
];
raw_data
| invoke pairwise_dist_fl('name', 'type')
| where _partition == 'Person' | sort by entity asc, entity1 asc
| evaluate pivot (entity, max(dist), entity1) | sort by entity1 asc

Output

entity1 Andy Betsy Cindy Dan Elmie Franny Godzilla Hannie ...
Andy 0.354 0.4125 0.1887 0.4843 0.3702 1.2087 0.6265 ...
Betsy 0.354 0.416 0.4708 0.6307 0.0161 1.2051 0.4872 ...
Cindy 0.4125 0.416 0.6012 0.3575 0.3998 1.4783 0.214 ...
Dan 0.1887 0.4708 0.6012 0.673 0.487 1.0199 0.8152 ...
Elmie 0.4843 0.6307 0.3575 0.673 0.6145 1.5502 0.1565 ...
Franny 0.3702 0.0161 0.3998 0.487 0.6145 1.2213 0,471 ...
Godzilla 1.2087 1.2051 1.4783 1.0199 1.5502 1.2213 1.5495 ...
Hannie 0.6265 0.4872 0.214 0.8152 0.1565 0,471 1.5495 ...
... ... ... ... ... ... ... ... ... ...

Beim Betrachten von Entitäten zweier verschiedener Typen möchten wir den Abstand zwischen Entitäten berechnen, die demselben Typ angehören, indem sowohl Nominalvariablen (z. B. Geschlecht oder bevorzugtes Zubehör) als auch numerische Variablen (z. B. die Anzahl der Gliedmaßen, Höhe und Gewicht) berücksichtigt werden. Die numerischen Variablen befinden sich auf unterschiedlichen Skalierungen und müssen zentralisiert und skaliert werden, was automatisch erfolgt. Die Ausgabe ist Paare von Entitäten unter derselben Partition mit berechneter multivariate Entfernung. Sie kann direkt analysiert, als Entfernungsmatrix oder Punktdiagramm dargestellt oder als Eingabedaten für den Ausreißererkennungsalgorithmus verwendet werden, indem sie den mittleren Abstand pro Entität mit Entitäten mit hohen Werten berechnet, die globale Ausreißer angeben. Wenn Sie beispielsweise eine optionale Visualisierung mithilfe einer Abstandsmatrix hinzufügen, erhalten Sie eine Tabelle wie im Beispiel gezeigt. Aus dem Beispiel sehen Sie folgendes:

  • Einige Paare von Entitäten (Betsy und Franny) weisen einen niedrigen Abstandswert (nahe 0) auf, der angibt, dass sie ähnlich sind.
  • Einige Paare von Entitäten (Godzilla und Elmie) weisen einen hohen Abstandswert (1 oder höher) auf, der angibt, dass sie unterschiedlich sind.

Die Ausgabe kann weiter verwendet werden, um die durchschnittliche Entfernung pro Entität zu berechnen. Eine hohe durchschnittliche Entfernung kann auf globale Ausreißer hinweisen. So können wir beispielsweise sehen, dass Godzilla im Durchschnitt einen hohen Abstand von den anderen hat, der darauf hinweist, dass es ein wahrscheinlicher globaler Ausreißer ist.