Repository navigation
Build shifts, picks and n() from the columns' rows - #457
Merged
Merged
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
jbearak
marked this pull request as ready for review
October 27, 2026 00:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#456 builds a grouped
mutate()of arithmetic from the columns' rows when the tree holds only numbers,(, columns, summaries of columns and the four operators. A tree withlag()orlead()of a column,first(),last()ornth()of one, orn()still went to ADR 0065's plan of the chunks, which split each column and returned a result for each group. Over the 42,739 women in the first 100,000 rows of the India 2021 DHS births file,mutate(b, k = b3 - lag(b3), .by = caseid)took about 0.14 seconds, where a tibble takes about 0.46.This PR lets the rows evaluator of
C_dtatools_arith_plan_rows()take these operands, as the plan of the chunks computes them for each group:lag(x, n)orlead(x, n)gives each group's values of the column n rows before or after, within the group, and the default or a missing value where the shift leaves a row, in the column's storage.shift_default_number()must find that the storage holds the default, astree_shift()requires.first(x),last(x)ornth(x, n)gives each group's value of the column at that position, or a missing value past either end. Astree_pick()does, the call declines where a group has the position and the first group does not.n()gives each group's size as a bare integer. Arithmetic of a Stata numeric with it takes the Stata numeric's storage as the minimum, as with a number. Arithmetic of two bare numbers still goes to the plan of the chunks.slice_chunk_admitted()'s checks move toslice_storage_admitted(), which takes the chunk's size as an argument. The evaluator then checks the gathered rows once, with every group shorter than the size gate..arith_planned()now tries the rows first for trees with shifts, picks and sizes.Behavior
Values, attributes, ALTREP forms, warnings and errors are unchanged. ADR 0119 records the decision.
row_number()takes no arithmetic, as before, andx[1]andx[n()]still go to the plan of the chunks.Timing
Best of three runs in fresh R sessions, in seconds, with the builds interleaved, over the first 100,000 rows of the India 2021 DHS births file. Before is #456's head after its merge of main.
mutate(b, k = b3 - lag(b3), .by = caseid)mutate(b, k = b3 - first(b3), .by = caseid)mutate(b, k = b11 / n(), .by = caseid)GC time fell from about 0.015, 0.015 and 0.008 seconds to none in each call.
Tests
x - lag(x),lead(x, 3, default = 1L) * 2,x - nth(x, -2),x / n()and(x - lag(x)) / n() + first(x). Each must give the same value, warnings and result form with the plans as without them. 77 build their column from the rows. The 12th shape,x - nth(x, 3), reads a third row the first group lacks, so the loop runs, as before.n()over random data at each storage's limits.last()of a group that ends in one errors in the loop, with the plan too.lag()andlead()keep such a value, but the plan declines a slice that holds one, and builds the column where no slice does.int / n()andbyte - lag(byte). The existing case ofb - first(b)over the old file still errors in the loop, with the plan declining.