Suppose I have a list of data, and a list of quantiles ({0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}
is a perennial favorite), and I want to assign to each element the quantile it is in (so for Range[100], the first ten numbers will be in the 0th quantile, I guess, the second ten in the first, and so on). Now, there is a way of doing this by ranking all the data by PermutationList[FindPermutation[Ordering[mydata]]]
, and then operating with the ranking, but this seems clumsy. Any slicker way?
2 Answers
MapIndexed[#2[[1]] - 1 &, #, {2}] &@
BinLists[#, {Flatten[{0, Quantile[#, quantiles], 1.1 Max@#}]}] & @ Range[100]
{{0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
{6, 6, 6, 6, 6, 6, 6, 6, 6, 6}, {7, 7, 7, 7, 7, 7, 7, 7, 7, 7},
{8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}}
-
$\begingroup$ At this juncture, I should leave the reminder that the default setting for the third argument of
Quantile[]
might not be the same as the convention you're accustomed to. Check the docs, and explicitly specify the third argument, if in doubt. $\endgroup$ Commented Mar 21, 2017 at 11:46
@kglr points in the right direction, though I'm not sure that this is exactly what you want. For your pretty simple case why not implicitly rank the data by sorting it first? E.g.:
data = Transpose[{Range@Length@#, #}] &@ Sort@RandomVariate[NormalDistribution[], 20];
To get quantiles we write this function:
quantile[data_, q:{a_?NumericQ, b_?NumericQ}] :=
Part[data, Max[1, Floor[a Length[data]] + 1] ;; Min[Length[data], Floor[b Length[data]]]]
quantile[data_, qs:{{_?NumericQ, _?NumericQ}..}] :=
Table[quantile[data, q], {q, qs}]
then we can get a list of the elements belonging to each decile, partitioned by decile like so:
quantile[data, Partition[Range[0.0, 1.0, 0.1], 2, 1]];
Flatten[%, 1] == data (* True *)
ListPlot[%%]