Skip to content

Commit

Permalink
Merge pull request #2930 from finos/quartiles
Browse files Browse the repository at this point in the history
Quartiles
  • Loading branch information
texodus authored Feb 27, 2025
2 parents 7ce0150 + 7c9dc45 commit 832c14e
Show file tree
Hide file tree
Showing 16 changed files with 1,570 additions and 1,160 deletions.
8 changes: 8 additions & 0 deletions cpp/perspective/src/cpp/aggspec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ t_aggspec::agg_str() const {
case AGGTYPE_ANY: {
return "any";
} break;
case AGGTYPE_Q1: {
return "q1";
} break;
case AGGTYPE_Q3: {
return "q3";
} break;
case AGGTYPE_MEDIAN: {
return "median";
} break;
Expand Down Expand Up @@ -343,6 +349,8 @@ t_aggspec::get_output_specs(const t_schema& schema) const {
case AGGTYPE_ANY:
case AGGTYPE_UNIQUE:
case AGGTYPE_DOMINANT:
case AGGTYPE_Q1:
case AGGTYPE_Q3:
case AGGTYPE_MEDIAN:
case AGGTYPE_FIRST:
case AGGTYPE_LAST_BY_INDEX:
Expand Down
6 changes: 6 additions & 0 deletions cpp/perspective/src/cpp/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,12 @@ str_to_aggtype(const std::string& str) {
if (str == "any") {
return t_aggtype::AGGTYPE_ANY;
}
if (str == "q1") {
return t_aggtype::AGGTYPE_Q1;
}
if (str == "q3") {
return t_aggtype::AGGTYPE_Q3;
}
if (str == "median") {
return t_aggtype::AGGTYPE_MEDIAN;
}
Expand Down
2 changes: 2 additions & 0 deletions cpp/perspective/src/cpp/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ t_config::setup(
case AGGTYPE_MEAN:
case AGGTYPE_WEIGHTED_MEAN:
case AGGTYPE_UNIQUE:
case AGGTYPE_Q1:
case AGGTYPE_Q3:
case AGGTYPE_MEDIAN:
case AGGTYPE_JOIN:
case AGGTYPE_DOMINANT:
Expand Down
2 changes: 2 additions & 0 deletions cpp/perspective/src/cpp/extract_aggregate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ extract_aggregate(
case AGGTYPE_COUNT:
case AGGTYPE_ANY:
case AGGTYPE_DOMINANT:
case AGGTYPE_Q1:
case AGGTYPE_Q3:
case AGGTYPE_MEDIAN:
case AGGTYPE_FIRST:
case AGGTYPE_AND:
Expand Down
55 changes: 48 additions & 7 deletions cpp/perspective/src/cpp/sparse_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,42 @@ t_stree::update_agg_table(

dst->set_scalar(dst_ridx, new_value);
} break;
case AGGTYPE_Q1: {
old_value.set(dst->get_scalar(dst_ridx));
auto pkeys = get_pkeys(nidx);
new_value.set(
reduce_from_gstate<
std::function<t_tscalar(std::vector<t_tscalar>&)>>(
gstate,
expression_master_table,
spec.get_dependencies()[0].name(),
pkeys,
[&](std::vector<t_tscalar>& values) {
return get_aggregate_median(values, 0.25);
}
)
);

dst->set_scalar(dst_ridx, new_value);
} break;
case AGGTYPE_Q3: {
old_value.set(dst->get_scalar(dst_ridx));
auto pkeys = get_pkeys(nidx);
new_value.set(
reduce_from_gstate<
std::function<t_tscalar(std::vector<t_tscalar>&)>>(
gstate,
expression_master_table,
spec.get_dependencies()[0].name(),
pkeys,
[&](std::vector<t_tscalar>& values) {
return get_aggregate_median(values, 0.75);
}
)
);

dst->set_scalar(dst_ridx, new_value);
} break;
case AGGTYPE_MEDIAN: {
old_value.set(dst->get_scalar(dst_ridx));
auto pkeys = get_pkeys(nidx);
Expand All @@ -1335,7 +1371,7 @@ t_stree::update_agg_table(
spec.get_dependencies()[0].name(),
pkeys,
[&](std::vector<t_tscalar>& values) {
return get_aggregate_median(values);
return get_aggregate_median(values, 0.5);
}
)
);
Expand Down Expand Up @@ -2326,26 +2362,31 @@ t_stree::get_aggregate(t_index idx, t_index aggnum) const {
}

t_tscalar
t_stree::get_aggregate_median(std::vector<t_tscalar>& values) const {
int size = values.size();
bool is_even_size = size % 2 == 0;

t_stree::get_aggregate_median(std::vector<t_tscalar>& values, float n) const {
const auto size = values.size();
const float raw_size = static_cast<float>(size) * n;
bool is_even_size = fabsf(roundf(raw_size) - raw_size) <= 0.00001;
if (size == 0) {
return {};
}

if (size == 1) {
return values[0];
}

const auto split = static_cast<long>(raw_size);
if (is_even_size && values[0].is_floating_point()) {
t_tscalar median_average;
auto middle = values.begin() + (size / 2);
auto middle = values.begin() + split;
nth_element(values.begin(), middle, values.end());
median_average.set(
(*middle + *(middle - 1)) / static_cast<t_tscalar>(2)
);

return median_average;
}
auto middle = values.begin() + (size / 2);

auto middle = values.begin() + split;
std::nth_element(values.begin(), middle, values.end());
return *middle;
}
Expand Down
2 changes: 2 additions & 0 deletions cpp/perspective/src/include/perspective/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ enum t_aggtype {
AGGTYPE_WEIGHTED_MEAN,
AGGTYPE_UNIQUE,
AGGTYPE_ANY,
AGGTYPE_Q1,
AGGTYPE_Q3,
AGGTYPE_MEDIAN,
AGGTYPE_JOIN,
AGGTYPE_SCALED_DIV,
Expand Down
3 changes: 2 additions & 1 deletion cpp/perspective/src/include/perspective/sparse_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,8 @@ class PERSPECTIVE_EXPORT t_stree {

t_tscalar get_aggregate(t_index idx, t_index aggnum) const;

t_tscalar get_aggregate_median(std::vector<t_tscalar>& values) const;
t_tscalar
get_aggregate_median(std::vector<t_tscalar>& values, float n) const;

void get_child_indices(t_index idx, std::vector<t_index>& out_data) const;

Expand Down
16 changes: 16 additions & 0 deletions rust/perspective-client/src/rust/config/aggregates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ pub enum SingleAggregate {
#[serde(rename = "dominant")]
Dominant,

#[serde(rename = "q1")]
Q1,

#[serde(rename = "q3")]
Q3,

#[serde(rename = "median")]
Median,

Expand Down Expand Up @@ -117,6 +123,8 @@ impl Display for SingleAggregate {
Self::Unique => "unique",
Self::Dominant => "dominant",
Self::Median => "median",
Self::Q1 => "q1",
Self::Q3 => "q3",
Self::First => "first",
Self::FirstByIndex => "first by index",
Self::LastByIndex => "last by index",
Expand Down Expand Up @@ -155,6 +163,8 @@ impl FromStr for SingleAggregate {
"unique" => Ok(Self::Unique),
"dominant" => Ok(Self::Dominant),
"median" => Ok(Self::Median),
"q1" => Ok(Self::Q1),
"q3" => Ok(Self::Q3),
"first by index" => Ok(Self::FirstByIndex),
"first" => Ok(Self::First),
"last by index" => Ok(Self::LastByIndex),
Expand Down Expand Up @@ -241,6 +251,8 @@ const STRING_AGGREGATES: &[SingleAggregate] = &[
SingleAggregate::Last,
SingleAggregate::LastByIndex,
SingleAggregate::Median,
SingleAggregate::Q1,
SingleAggregate::Q3,
SingleAggregate::Unique,
];

Expand All @@ -262,6 +274,8 @@ const NUMBER_AGGREGATES: &[SingleAggregate] = &[
SingleAggregate::Last,
SingleAggregate::Mean,
SingleAggregate::Median,
SingleAggregate::Q1,
SingleAggregate::Q3,
SingleAggregate::PctSumParent,
SingleAggregate::PctSumGrandTotal,
SingleAggregate::StdDev,
Expand All @@ -286,6 +300,8 @@ const DATETIME_AGGREGATES: &[SingleAggregate] = &[
SingleAggregate::LastByIndex,
SingleAggregate::Last,
SingleAggregate::Median,
SingleAggregate::Q1,
SingleAggregate::Q3,
SingleAggregate::Unique,
];

Expand Down
5 changes: 0 additions & 5 deletions rust/perspective-js/src/rust/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ use wasm_bindgen::prelude::*;
pub use crate::table::*;
use crate::utils::{inherit_docs, ApiError, ApiResult, JsValueSerdeExt, LocalPollLoop};

#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
import type {TableInitOptions} from "@finos/perspective";
"#;

#[wasm_bindgen]
extern "C" {
#[derive(Clone)]
Expand Down
10 changes: 5 additions & 5 deletions rust/perspective-js/src/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ export type * from "../../src/ts/ts-rs/ViewOnUpdateResp.d.ts";
export type * from "../../src/ts/ts-rs/OnUpdateOptions.d.ts";
export type * from "../../src/ts/ts-rs/UpdateOptions.d.ts";
import type * as view_window from "../../src/ts/ts-rs/ViewWindow.d.ts";
import type * as table_init_options from "../../src/ts/ts-rs/TableInitOptions.d.ts";
import type * as view_config_update from "../../src/ts/ts-rs/ViewConfigUpdate.d.ts";
import type {ViewWindow} from "../../src/ts/ts-rs/ViewWindow.d.ts";
import type {TableInitOptions} from "../../src/ts/ts-rs/TableInitOptions.d.ts";
import type {ViewConfigUpdate} from "../../src/ts/ts-rs/ViewConfigUpdate.d.ts";
import type * as on_update_args from "../../src/ts/ts-rs/ViewOnUpdateResp.d.ts";
import type * as on_update_options from "../../src/ts/ts-rs/OnUpdateOptions.d.ts";
import type * as update_options from "../../src/ts/ts-rs/UpdateOptions.d.ts";
import type {OnUpdateOptions} from "../../src/ts/ts-rs/OnUpdateOptions.d.ts";
import type {UpdateOptions} from "../../src/ts/ts-rs/UpdateOptions.d.ts";
"#;

#[cfg(feature = "export-init")]
Expand Down
5 changes: 0 additions & 5 deletions rust/perspective-js/src/rust/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,6 @@ impl Table {
}
}

#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
import type {UpdateOptions, ViewConfigUpdate} from "@finos/perspective";
"#;

#[wasm_bindgen]
extern "C" {
// TODO Fix me
Expand Down
5 changes: 0 additions & 5 deletions rust/perspective-js/src/rust/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ use wasm_bindgen_futures::spawn_local;
use crate::table::Table;
use crate::utils::{inherit_docs, ApiFuture, ApiResult, JsValueSerdeExt, LocalPollLoop};

#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
import type {OnUpdateOptions, ViewWindow} from "@finos/perspective";
"#;

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "ViewWindow")]
Expand Down
Loading

0 comments on commit 832c14e

Please # to comment.