Open-source agentic AI for transaction monitoring. Just ask Jooby.What's Jube? →

dplyr Gap Analysis

What of dplyr’s verb set has a real AdvancedAnalyticsTools equivalent today, what doesn’t, and which gaps are sensible to shim directly on an array versus better left to the SQL/query layer that already sits in front of AdvancedAnalyticsCache. Companion to Data Frames vs the Packed Array, which covers the conceptual mapping; this is the practical punch list.

The shape to shim against

Every existing table-shaped tool in Jube.Service/Agent/AdvancedAnalyticsTools/DataPreparationAndResampling/ works on a named jagged table — double[][] data (one array per row) plus a parallel string[] columnNames — not the flat, unnamed, row-major double[] that AdvancedAnalyticsCache/ AdvancedAnalyticsPacking.Pack/Unpack actually stores. SelectTableColumns, DropSparseRowsAndColumns and FindDuplicateRows (FeatureEngineeringTools.cs, MissingValueTools.cs, DataQualityTools.cs) all take this shape and share two guard helpers: DataPreparationGuard.Table(data, ...) (validates rectangularity, returns column count) and DataPreparationGuard.Names(columnNames, columns, ...) (validates or defaults names to column_0, column_1, …). A shim needs column identity to do anything dplyr-shaped at all — the flat packed array alone has none — so every recommendation below targets this same double[][] + string[] shape, returning FeatureTableResult(string[] ColumnNames, double[][] Table) where a full table comes back, so it composes with SelectTableColumns and the rest of the family without a new result type per verb.

Verb by verb

dplyr verb Current coverage Gap Verdict
select() Exact match: SelectTableColumns (FeatureEngineeringTools.cs:448) — keep named columns, in a given order None Covered
rename() None as a table operation Renaming is metadata-only (relabel columnNames, touch no cell) Not needed as a separate tool: the caller already holds columnNames and can replace an entry directly
relocate() Partial: SelectTableColumns with keep in the wanted order already reorders columns, but it can’t express “move X after Y, leave the rest as-is” without naming every column Reordering when you don’t want to also filter down to a subset Not covered beyond what SelectTableColumns’s reordering already provides
mutate() Partial, verb-shaped tools exist for specific transforms (ApplyColumnFunction, GenerateColumnPairFeatures, GenerateLagFeatures, EncodeCyclicalFeature, all in FeatureEngineeringTools.cs/ScalingTools.cs) No generic “compute a new column from an arbitrary expression over existing columns” — every existing tool is a fixed, named transform, not an expression evaluator Not covered as a generic escape hatch: an arbitrary-expression evaluator over the array is a different kind of tool, closer to the rule DSL than a data-prep tool
filter() Partial: several tools identify rows (FindDuplicateRows returns indices to drop, DropSparseRowsAndColumns drops by a missingness rule, sampling tools return an index subset) but none takes an arbitrary boolean predicate and returns the compacted table A generic “keep these row indices, return the smaller table” step — every existing tool stops at indices and leaves recombination to the caller The single highest-leverage gap: every row-selecting tool stops at indices and leaves recombination into a smaller table to the caller
arrange() Partial: SortValuesWithOriginalIndices/SortValuesByKeys (NumericsAndOptimisation/CombinatoricsAndUtilityTools.cs:447,463) sort one vector, optionally by a single parallel key vector No whole-table, multi-key, stable sort — you’d have to sort one column and manually permute every other array yourself No whole-table, multi-key sort exists; sorting one column and permuting every other array by hand is left entirely to the caller
distinct() Partial: FindDuplicateRows (DataQualityTools.cs:66) already computes exactly this — it returns the row indices to keep if you drop repeats — but it stops at reporting, no tool actually removes them Nothing missing conceptually, just the last step Nothing missing conceptually beyond the final step: FindDuplicateRows already identifies which rows to keep, but no tool removes the duplicates itself
slice() / head() / tail() None Row-range subsetting by position Not covered as a distinct tool; row-range subsetting by position has no dedicated tool
group_by() %>% summarise() Partial: SummariseByGroup (DescriptiveStatistics/TableAndTransformTools.cs:390) groups one numeric column by one label array, returning a fixed set of stats (count, mean, median, sd, min, max, sum) — not a user-chosen aggregation, not multiple simultaneous group/value columns Multi-column group-by, a caller-chosen aggregation per column, more than one grouping key SummariseByGroup covers a single key and a single value column with a fixed statistic set; a full relational group-by (multiple keys, a caller-chosen aggregation) is a genuinely different and larger thing than this single-key, single-value grouped summary
bind_rows() / bind_cols() None Concatenating two already-shaped tables Combining two independently-produced tables is ordinarily something the SQL query that produced them should already have done before packing
left_join() / inner_join() / anti_join() / semi_join() None anywhere in AdvancedAnalyticsTools (checked the whole tree, not just this group) Key-based row matching across two tables Not possible on the array: a join needs a key concept the packed array has no notion of at all (rows are bare positions, not identified by any column), and matching keys across two independently-produced tables is exactly what the SQL layer upstream of AdvancedAnalyticsCache already does before anything is packed, as already noted in DataFramesVsAccordArrays.md
pivot_longer() / pivot_wider() None Reshaping between wide and long form Same call as joins: reshape before packing, at the query layer, where column identity still exists in a form worth reshaping. Not sensible on a positional array