Simple example
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; auto x = [3.0, 1.0, 4.0, 2.0, 0.0].sliced; assert(x.quantile(0.5).approxEqual(2.0)); auto qtile = [0.25, 0.75].sliced; assert(x.quantile(qtile).all!approxEqual([1.0, 3.0])); assert(x.quantile(0.25, 0.75).all!approxEqual([1.0, 3.0]));
Modify probability in place
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; auto x = [3.0, 1.0, 4.0, 2.0, 0.0].sliced; auto qtile = [0.25, 0.75].sliced; auto qtile_copy = qtile.dup; x.quantile!("type7", false, true)(qtile); assert(qtile.all!approxEqual([1.0, 3.0])); assert(!qtile.all!approxEqual(qtile_copy));
Quantile of vector
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; auto x = [1.0, 9.8, 0.2, 8.5, 5.8, 3.5, 4.5, 8.2, 5.2, 5.2, 2.5, 1.8, 2.2, 3.8, 5.2, 9.2, 6.2, 9.2, 9.2, 8.5].sliced; assert(x.quantile(0.5).approxEqual(5.20)); auto qtile = [0.25, 0.75].sliced; assert(x.quantile(qtile).all!approxEqual([3.250, 8.500]));
Quantile of matrix
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.fuse: fuse; import mir.ndslice.slice: sliced; auto x = [ [1.0, 9.8, 0.2, 8.5, 5.8, 3.5, 4.5, 8.2, 5.2, 5.2], [2.5, 1.8, 2.2, 3.8, 5.2, 9.2, 6.2, 9.2, 9.2, 8.5] ].fuse; assert(x.quantile(0.5).approxEqual(5.20)); auto qtile = [0.25, 0.75].sliced; assert(x.quantile(qtile).all!approxEqual([3.250, 8.500]));
Row quantile of matrix
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.fuse: fuse; import mir.ndslice.slice: sliced; import mir.ndslice.topology: alongDim, byDim, map, flattened; auto x = [ [1.0, 9.8, 0.2, 8.5, 5.8, 3.5, 4.5, 8.2, 5.2, 5.2], [2.5, 1.8, 2.2, 3.8, 5.2, 9.2, 6.2, 9.2, 9.2, 8.5] ].fuse; auto result0 = [5.200, 5.700]; // Use byDim or alongDim with map to compute median of row/column. assert(x.byDim!0.map!(a => a.quantile(0.5)).all!approxEqual(result0)); assert(x.alongDim!1.map!(a => a.quantile(0.5)).all!approxEqual(result0)); auto qtile = [0.25, 0.75].sliced; auto result1 = [[3.750, 7.600], [2.825, 9.025]]; assert(x.byDim!0.map!(a => a.quantile(qtile)).all!(all!approxEqual)(result1));
Allow modification of input
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; auto x = [3.0, 1.0, 4.0, 2.0, 0.0].sliced; auto x_copy = x.dup; auto result = x.quantile!(QuantileAlgo.type7, true)(0.5); assert(!x.all!approxEqual(x_copy));
Double-check probability is not modified
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; auto x = [3.0, 1.0, 4.0, 2.0, 0.0].sliced; auto qtile = [0.25, 0.75].sliced; auto qtile_copy = qtile.dup; auto result = x.quantile!("type7", false, false)(qtile); assert(result.all!approxEqual([1.0, 3.0])); assert(qtile.all!approxEqual(qtile_copy));
Can also set algorithm type
import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; auto x = [1.0, 9.8, 0.2, 8.5, 5.8, 3.5, 4.5, 8.2, 5.2, 5.2, 2.5, 1.8, 2.2, 3.8, 5.2, 9.2, 6.2, 9.2, 9.2, 8.5].sliced; assert(x.quantile!"type1"(0.5).approxEqual(5.20)); assert(x.quantile!"type2"(0.5).approxEqual(5.20)); assert(x.quantile!"type3"(0.5).approxEqual(5.20)); assert(x.quantile!"type4"(0.5).approxEqual(5.20)); assert(x.quantile!"type5"(0.5).approxEqual(5.20)); assert(x.quantile!"type6"(0.5).approxEqual(5.20)); assert(x.quantile!"type7"(0.5).approxEqual(5.20)); assert(x.quantile!"type8"(0.5).approxEqual(5.20)); assert(x.quantile!"type9"(0.5).approxEqual(5.20));
Can also set algorithm or output type
import mir.ndslice.slice: sliced; auto a = [1, 1e100, 1, -1e100].sliced; auto x = a * 10_000; auto result0 = x.quantile!float(0.5); assert(result0 == 10_000f); static assert(is(typeof(result0) == float)); auto result1 = x.quantile!(float, "type8")(0.5); assert(result1 == 10_000f); static assert(is(typeof(result1) == float));
Support for integral and user-defined types for type 1 & 3
import mir.ndslice.topology: repeat; auto x = uint.max.repeat(3); assert(x.quantile!(uint, "type1")(0.5) == uint.max); assert(x.quantile!(uint, "type3")(0.5) == uint.max); static struct Foo { float x; alias x this; } Foo[] foo = [Foo(1f), Foo(2f), Foo(3f)]; assert(foo.quantile!"type1"(0.5) == 2f); assert(foo.quantile!"type3"(0.5) == 2f);
Compute quantile along specified dimention of tensors
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; import mir.ndslice.fuse: fuse; import mir.ndslice.topology: as, iota, alongDim, map, repeat; auto x = [ [0.0, 1, 3], [4.0, 5, 7] ].fuse; assert(x.quantile(0.5).approxEqual(3.5)); auto m0 = [2.0, 3.0, 5.0]; assert(x.alongDim!0.map!(a => a.quantile(0.5)).all!approxEqual(m0)); assert(x.alongDim!(-2).map!(a => a.quantile(0.5)).all!approxEqual(m0)); auto m1 = [1.0, 5.0]; assert(x.alongDim!1.map!(a => a.quantile(0.5)).all!approxEqual(m1)); assert(x.alongDim!(-1).map!(a => a.quantile(0.5)).all!approxEqual(m1)); assert(iota(2, 3, 4, 5).as!double.alongDim!0.map!(a => a.quantile(0.5)).all!approxEqual(iota([3, 4, 5], 3 * 4 * 5 / 2)));
Support for array
import mir.algorithm.iteration: all; import mir.math.common: approxEqual; double[] x = [3.0, 1.0, 4.0, 2.0, 0.0]; assert(x.quantile(0.5).approxEqual(2.0)); double[] qtile = [0.25, 0.75]; assert(x.quantile(qtile).all!approxEqual([1.0, 3.0]));