60 static std::vector<double>
rankdata(
const std::vector<T>& a,
65 const std::size_t n = a.size();
66 std::vector<double> ranks(n, std::numeric_limits<double>::quiet_NaN());
68 if (n == 0)
return ranks;
71 auto is_nan_at = [&](std::size_t i) ->
bool {
72 if constexpr (std::is_floating_point<T>::value) {
73 return std::isnan(a[i]);
81 if constexpr (std::is_floating_point<T>::value)
83 for (std::size_t i = 0; i < n; ++i) {
if (is_nan_at(i)) { any_nan =
true;
break; } }
95 throw std::invalid_argument(
"RankData::rankdata: NaNs present but nan_policy=Raise.");
103 std::vector<std::size_t> idx;
105 for (std::size_t i = 0; i < n; ++i)
119 std::stable_sort(idx.begin(), idx.end(),
120 [&](std::size_t i, std::size_t j)
123 const D vi = static_cast<D>(a[i]);
124 const D vj = static_cast<D>(a[j]);
129 auto assign_block_rank = [&](std::size_t lo, std::size_t hi,
double value)
131 for (std::size_t k = lo; k < hi; ++k)
133 ranks[idx[k]] = value;
144 for (std::size_t pos = 0; pos < idx.size(); ++pos)
146 ranks[idx[pos]] =
static_cast<double>(pos + 1);
155 std::size_t dense_rank = 1;
156 while (lo < idx.size())
158 std::size_t hi = lo + 1;
159 const D v =
static_cast<D
>(a[idx[lo]]);
160 while (hi < idx.size() &&
static_cast<D
>(a[idx[hi]]) == v) ++hi;
162 assign_block_rank(lo, hi,
static_cast<double>(dense_rank));
176 while (lo < idx.size())
178 std::size_t hi = lo + 1;
179 const D v =
static_cast<D
>(a[idx[lo]]);
180 while (hi < idx.size() &&
static_cast<D
>(a[idx[hi]]) == v) ++hi;
183 const double r_min =
static_cast<double>(lo + 1);
184 const double r_max =
static_cast<double>(hi);
185 double r_value = 0.0;
188 else r_value = 0.5 * (r_min + r_max);
190 assign_block_rank(lo, hi, r_value);