Loading...
Searching...
No Matches
ktau.hpp
1// Copyright © 2020 Thomas Nagler
2//
3// This file is part of the wdm library and licensed under the terms of
4// the MIT license. For a copy, see the LICENSE file in the root directory
5// or https://github.com/tnagler/wdm/blob/master/LICENSE.
6
7#pragma once
8
9#include "utils.hpp"
10
11namespace wdm {
12
13namespace impl {
14
15inline void
16normalize_weights(std::vector<double>& w)
17{
18 if (w.size() > 0) {
19 double s = utils::sum(w);
20 for (size_t i = 0; i < w.size(); i++)
21 w[i] /= s;
22 }
23}
24
28inline double
29ktau(std::vector<double> x,
30 std::vector<double> y,
31 std::vector<double> weights = std::vector<double>())
32{
33 utils::check_sizes(x, y, weights);
34
35 // 1.1 Sort x, y, and weights in x order; break ties in according to y.
36 utils::sort_all(x, y, weights);
37
38 // 1.2 Count pairs of tied x and simultaneous ties in x and y.
39 double ties_x = utils::count_tied_pairs(x, weights);
40 double ties_both = utils::count_joint_ties(x, y, weights);
41
42 // 2.1 Sort y again and count exchanges (= number of discordant pairs).
43 double num_d = 0.0;
44 utils::merge_sort(y, weights, num_d);
45
46 // 2.2 Count pairs of tied y.
47 double ties_y = utils::count_tied_pairs(y, weights);
48
49 // 3. Calculate Kendall's tau.
50 if (weights.size() == 0)
51 weights = std::vector<double>(x.size(), 1.0);
52 double num_pairs = utils::perm_sum(weights, 2);
53 double num_c = num_pairs - (num_d + ties_x + ties_y - ties_both);
54 double tau = num_c - num_d;
55 tau /= std::sqrt((num_pairs - ties_x) * (num_pairs - ties_y));
56
57 return tau;
58}
59
61inline double
62ktau_stat_adjust(std::vector<double> x,
63 std::vector<double> y,
64 std::vector<double> weights)
65{
66 utils::check_sizes(x, y, weights);
67
68 if (weights.size() == 0)
69 weights = std::vector<double>(x.size(), 1.0);
70 // Put weights in effective-sample-size units: both their sum and squared
71 // sum then equal n_eff, while their relative magnitudes remain unchanged.
72 double effective_scale =
73 utils::sum(weights) / utils::sum(utils::pow(weights, 2));
74 for (auto& weight : weights)
75 weight *= effective_scale;
76
77 // 1.1 Sort x, y, and weights in x order; break ties in according to y.
78 utils::sort_all(x, y, weights);
79
80 // 1.2 Count pairs and triplets of tied x and simultaneous ties in x and y.
81 double pair_x = utils::count_tied_pairs(x, weights);
82 double trip_x = utils::count_tied_triplets(x, weights);
83 double v_x = utils::count_ties_v(x, weights);
84
85 // 2.1 Sort y and weights in y order; break ties according to x.
86 utils::sort_all(y, x, weights);
87
88 // 2.2 Count pairs and triplets of tied y.
89 double pair_y = utils::count_tied_pairs(y, weights);
90 double trip_y = utils::count_tied_triplets(y, weights);
91 double v_y = utils::count_ties_v(y, weights);
92
93 // 3. Calculate adjustment factor.
94 double s = utils::sum(weights);
95 double s2 = utils::perm_sum(weights, 2);
96 double s3 = utils::perm_sum(weights, 3);
97 double v_0 = 2 * s2 * (2 * s + 5);
98 double v_1 = 2 * pair_x * 2 * pair_y / (2 * 2 * s2);
99 double v_2 = 6 * trip_x * 6 * trip_y / (9 * 6 * s3);
100 double v = (v_0 - v_x - v_y) / 18 + v_1 + v_2;
101 return std::sqrt((s2 - pair_x) * (s2 - pair_y) / v);
102}
103
104}
105
106}
Weighted dependence measures.
Definition wdm.hpp:19