Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Quartiles #2930

Merged
merged 2 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading