Skip to content

Commit 538ce71

Browse files
committed
Add gmv aggregate
Signed-off-by: Andrew Stein <steinlink@gmail.com>
1 parent 643b74a commit 538ce71

8 files changed

Lines changed: 185 additions & 1 deletion

File tree

rust/perspective-python/perspective/tests/table/test_view.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,118 @@ def test_view_aggregate_mean(self):
424424
{"__ROW_PATH__": ["a"], "y": 300 / 2},
425425
]
426426

427+
def test_view_aggregate_gmv(self):
428+
data = {
429+
"division": [
430+
"D1",
431+
"D2",
432+
"D1",
433+
"D2",
434+
"D1",
435+
"D2",
436+
"D1",
437+
"D2",
438+
"D1",
439+
"D2",
440+
"D1",
441+
"D2",
442+
"D1",
443+
"D2",
444+
"D1",
445+
"D2",
446+
"D1",
447+
"D2",
448+
"D1",
449+
"D2",
450+
],
451+
"trading area": [
452+
"A",
453+
"B",
454+
"C",
455+
"D",
456+
"E",
457+
"A",
458+
"B",
459+
"C",
460+
"D",
461+
"E",
462+
"A",
463+
"B",
464+
"C",
465+
"D",
466+
"E",
467+
"A",
468+
"B",
469+
"C",
470+
"D",
471+
"E",
472+
],
473+
"symbol": [
474+
"AAPL",
475+
"GOOG",
476+
"MSFT",
477+
"AAPL",
478+
"GOOG",
479+
"MSFT",
480+
"AAPL",
481+
"GOOG",
482+
"MSFT",
483+
"AAPL",
484+
"GOOG",
485+
"MSFT",
486+
"AAPL",
487+
"GOOG",
488+
"MSFT",
489+
"AAPL",
490+
"GOOG",
491+
"MSFT",
492+
"AAPL",
493+
"GOOG",
494+
],
495+
"MV": [
496+
1500,
497+
1200,
498+
1300,
499+
1400,
500+
1600,
501+
1100,
502+
1700,
503+
1800,
504+
1900,
505+
2000,
506+
-2100,
507+
-2200,
508+
-2300,
509+
-2400,
510+
-2500,
511+
-2600,
512+
-2700,
513+
-2800,
514+
-2900,
515+
-3000,
516+
],
517+
}
518+
519+
tbl = Table(data)
520+
view = tbl.view(
521+
aggregates={"MV": "gmv"}, group_by=["division", "symbol"], columns=["MV"]
522+
)
523+
524+
assert view.to_columns() == {
525+
"__ROW_PATH__": [
526+
[],
527+
["D1"],
528+
["D1", "AAPL"],
529+
["D1", "GOOG"],
530+
["D1", "MSFT"],
531+
["D2"],
532+
["D2", "AAPL"],
533+
["D2", "GOOG"],
534+
["D2", "MSFT"],
535+
],
536+
"MV": [10000, 5900, -2000, -3200, 700, 7100, 800, -2400, -3900],
537+
}
538+
427539
def test_view_aggregate_mean_from_schema(self):
428540
data = [
429541
{"a": "a", "x": 1, "y": 200},

rust/perspective-server/cpp/perspective/src/cpp/aggspec.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ t_aggspec::agg_str() const {
247247
case AGGTYPE_STANDARD_DEVIATION: {
248248
return "stddev";
249249
}
250+
case AGGTYPE_GMV: {
251+
return "gmv";
252+
}
250253
default: {
251254
PSP_COMPLAIN_AND_ABORT("Unknown agg type");
252255
return "unknown";
@@ -343,6 +346,7 @@ t_aggspec::get_output_specs(const t_schema& schema) const {
343346
case AGGTYPE_SUM:
344347
case AGGTYPE_SUM_ABS:
345348
case AGGTYPE_ABS_SUM:
349+
case AGGTYPE_GMV:
346350
case AGGTYPE_PCT_SUM_PARENT:
347351
case AGGTYPE_PCT_SUM_GRAND_TOTAL:
348352
case AGGTYPE_MUL:

rust/perspective-server/cpp/perspective/src/cpp/base.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,9 @@ str_to_aggtype(const std::string& str) {
589589
if (str == "stddev" || str == "standard deviation") {
590590
return t_aggtype::AGGTYPE_STANDARD_DEVIATION;
591591
}
592+
if (str == "gmv") {
593+
return t_aggtype::AGGTYPE_GMV;
594+
}
592595

593596
std::stringstream ss;
594597
ss << "Encountered unknown aggregate operation: '" << str << "'"

rust/perspective-server/cpp/perspective/src/cpp/config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ t_config::setup(
226226
case AGGTYPE_SUM_NOT_NULL:
227227
case AGGTYPE_SUM_ABS:
228228
case AGGTYPE_ABS_SUM:
229+
case AGGTYPE_GMV:
229230
case AGGTYPE_MUL:
230231
case AGGTYPE_DISTINCT_COUNT:
231232
case AGGTYPE_DISTINCT_LEAF:

rust/perspective-server/cpp/perspective/src/cpp/extract_aggregate.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extract_aggregate(
5454
case AGGTYPE_SUM:
5555
case AGGTYPE_SUM_ABS:
5656
case AGGTYPE_ABS_SUM:
57+
case AGGTYPE_GMV:
5758
case AGGTYPE_SUM_NOT_NULL:
5859
case AGGTYPE_MUL:
5960
case AGGTYPE_COUNT:

rust/perspective-server/cpp/perspective/src/cpp/server.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,7 @@ ProtoServer::_handle_request(std::uint32_t client_id, Request&& req) {
14531453
number_opts.add_aggregates()->set_name("distinct count");
14541454
number_opts.add_aggregates()->set_name("dominant");
14551455
number_opts.add_aggregates()->set_name("first");
1456+
number_opts.add_aggregates()->set_name("gmv");
14561457
number_opts.add_aggregates()->set_name("high");
14571458
number_opts.add_aggregates()->set_name("low");
14581459
number_opts.add_aggregates()->set_name("max");

rust/perspective-server/cpp/perspective/src/cpp/sparse_tree.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,67 @@ t_stree::update_agg_table(
18151815
);
18161816
dst->set_scalar(dst_ridx, new_value);
18171817
} break;
1818+
case AGGTYPE_GMV: {
1819+
// Leaf nodes: plain `sum` of the underlying rows.
1820+
// Non-leaf nodes: sum over immediate children of
1821+
// `abs(sum(child_subtree))`. The child sums are recomputed
1822+
// from the gstate rather than read from already-populated
1823+
// child rows, so the parent does not see the abs-rolled-up
1824+
// child value — it sees the child's raw signed sum.
1825+
old_value.set(dst->get_scalar(dst_ridx));
1826+
const auto& col_name = spec.get_dependencies()[0].name();
1827+
auto dst_dtype = dst->get_dtype();
1828+
auto sum_reducer = [dst_dtype](std::vector<t_tscalar>& values
1829+
) -> t_tscalar {
1830+
if (values.empty()) {
1831+
return mknone();
1832+
}
1833+
t_tscalar v;
1834+
v.set(std::uint64_t(0));
1835+
v.m_type = dst_dtype;
1836+
for (const auto& x : values) {
1837+
if (x.is_nan()) {
1838+
continue;
1839+
}
1840+
v = v.add(x.coerce_numeric_dtype(dst_dtype));
1841+
}
1842+
return v;
1843+
};
1844+
1845+
if (is_leaf(nidx)) {
1846+
auto pkeys = get_pkeys(nidx);
1847+
new_value.set(
1848+
reduce_from_gstate<std::function<
1849+
t_tscalar(std::vector<t_tscalar>&)>>(
1850+
gstate,
1851+
expression_master_table,
1852+
col_name,
1853+
pkeys,
1854+
sum_reducer
1855+
)
1856+
);
1857+
} else {
1858+
t_tscalar rval;
1859+
rval.set(std::uint64_t(0));
1860+
rval.m_type = dst_dtype;
1861+
for (auto cidx : get_child_idx(nidx)) {
1862+
auto cpkeys = get_pkeys(cidx);
1863+
t_tscalar csum = reduce_from_gstate<std::function<
1864+
t_tscalar(std::vector<t_tscalar>&)>>(
1865+
gstate,
1866+
expression_master_table,
1867+
col_name,
1868+
cpkeys,
1869+
sum_reducer
1870+
);
1871+
if (csum.is_valid() && !csum.is_nan()) {
1872+
rval = rval.add(csum.abs());
1873+
}
1874+
}
1875+
new_value.set(rval);
1876+
}
1877+
dst->set_scalar(dst_ridx, new_value);
1878+
} break;
18181879
case AGGTYPE_MUL: {
18191880
old_value.set(dst->get_scalar(dst_ridx));
18201881
auto pkeys = get_pkeys(nidx);

rust/perspective-server/cpp/perspective/src/include/perspective/base.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ enum t_aggtype {
293293
AGGTYPE_PCT_SUM_PARENT,
294294
AGGTYPE_PCT_SUM_GRAND_TOTAL,
295295
AGGTYPE_VARIANCE,
296-
AGGTYPE_STANDARD_DEVIATION
296+
AGGTYPE_STANDARD_DEVIATION,
297+
AGGTYPE_GMV
297298
};
298299

299300
PERSPECTIVE_EXPORT t_aggtype str_to_aggtype(const std::string& str);

0 commit comments

Comments
 (0)