Udostępnij za pośrednictwem


pairwise_dist_fl()

Oblicz odległości parowania między jednostkami na podstawie wielu zmiennych nominalnych i liczbowych.

Funkcja jest funkcją pairwise_dist_fl()zdefiniowaną przez użytkownika , która oblicza wieloariantową odległość między punktami danych należącymi do tej samej partycji, uwzględniając zmienne nominalne i liczbowe.

  • Wszystkie pola ciągów oprócz nazw jednostek i partycji są uznawane za zmienne nominalne. Odległość jest równa 1, jeśli wartości są różne i 0, jeśli są takie same.
  • Wszystkie pola liczbowe są uznawane za zmienne liczbowe. Są one znormalizowane przez przekształcenie na wyniki z, a odległość jest obliczana jako wartość bezwzględna różnicy. Łączna wielokrotna odległość między punktami danych jest obliczana jako średnia odległości między zmiennymi.

Odległość zbliżona do zera oznacza, że jednostki są podobne, a odległość powyżej 1 oznacza, że są różne. Podobnie jednostka o średniej odległości zbliżonej do lub powyżej wskazuje, że różni się od wielu innych jednostek w partycji, co wskazuje potencjalną wartość odstawą.

Dane wyjściowe funkcji są parami odległości między jednostkami w ramach tej samej partycji. Można go używać jako do wyszukiwania podobnych lub różnych par. takie jak jednostki o minimalnych odległościach mają wiele typowych cech. Można go również łatwo przekształcić w macierz odległości (zobacz przykład użycia) lub użyć jako danych wejściowych dla algorytmów wykrywania klastrowania lub wartości odstających.

Składnia

pairwise_dist_fl(jednostka, partycja)

Dowiedz się więcej o konwencjach składniowych.

Parametry

Nazwa Typ Wymagane Opis
Jednostki string ✔️ Nazwa kolumny tabeli wejściowej zawierająca nazwy lub identyfikatory jednostek, dla których zostaną obliczone odległości.
Partycji string ✔️ Nazwa kolumny tabeli wejściowej zawierającej partycję lub zakres, dzięki czemu odległości są obliczane dla wszystkich par jednostek w ramach tej samej partycji.

Definicja funkcji

Funkcję można zdefiniować, osadzając jej kod jako funkcję zdefiniowaną przez zapytanie lub tworząc ją jako funkcję przechowywaną w bazie danych w następujący sposób:

Zdefiniuj funkcję przy użyciu następującej instrukcji let. Nie są wymagane żadne uprawnienia.

Ważne

Instrukcja let nie może być uruchamiana samodzielnie. Po nim musi znajdować się instrukcja wyrażenia tabelarycznego. Aby uruchomić działający przykład pairwise_dist_fl()polecenia , zobacz Przykład.

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.

Przykład

W poniższym przykładzie użyto operatora invoke do uruchomienia funkcji.

Aby użyć funkcji zdefiniowanej przez zapytanie, wywołaj ją po definicji funkcji osadzonej.

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

Dane wyjściowe

jednostka1 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 ...
... ... ... ... ... ... ... ... ... ...

Patrząc na jednostki dwóch różnych typów, chcemy obliczyć odległość między jednostkami należącymi do tego samego typu, uwzględniając zarówno zmienne nominalne (takie jak płeć lub preferowane metody dostępu) i zmienne liczbowe (takie jak liczba kończyn, wysokość i waga). Zmienne liczbowe są na różnych skalach i muszą być scentralizowane i skalowane, co jest wykonywane automatycznie. Dane wyjściowe to pary jednostek w tej samej partycji o obliczonej odległości wielowariancji. Można je analizować bezpośrednio, wizualizować jako macierz odległości lub wykres punktowy albo używać jako danych wejściowych algorytmu wykrywania odstających przez obliczanie średniej odległości na jednostkę z jednostkami o wysokich wartościach wskazujących wartości odstające globalne. Na przykład podczas dodawania opcjonalnej wizualizacji przy użyciu macierzy odległości uzyskasz tabelę, jak pokazano w przykładzie. W przykładzie widać, że:

  • Niektóre pary jednostek (Betsy i Franny) mają niską wartość odległości (zbliżoną do 0) wskazującą, że są podobne.
  • Niektóre pary jednostek (Godzilla i Elmie) mają wysoką wartość odległości (1 lub nowszą) wskazującą, że są różne.

Dane wyjściowe można dodatkowo użyć do obliczenia średniej odległości na jednostkę. Wysoka średnia odległość może wskazywać na wartości odstające globalne. Na przykład widzimy, że średnio Godzilla ma dużą odległość od innych wskazujących, że jest to prawdopodobna globalna wartość odstający.