Repository navigation
Take a grouped slice's rows in one native call - #458
Merged
Merged
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
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
slice_min(),slice_max(),slice_head()andslice_tail()of a grouped dibble evaluated each group in the data mask.slice_min()andslice_max()read the group's chunk oforder_by, ranked it withvctrs::vec_rank(), and kept the rows ranked within the slice's size.slice_head()andslice_tail()took the group's first or last rows. Over the 42,739 women in the first 100,000 rows of the India 2021 DHS births file,slice_max(b, b2, n = 1, by = caseid)took about 1.0 seconds, where a tibble takes about 1.2, andslice_head(b, n = 1, by = caseid)about 0.14, where a tibble takes about 0.63.This PR takes the rows of every group after the first in one native call once the loop has evaluated the first group:
C_dtatools_slice_position_plan()copies each group's first or last rows forslice_head()andslice_tail().C_dtatools_slice_rank_plan()handlesslice_min(x)andslice_max(x), where x names a compact Stata numeric column that only the first group has read. It reads the key of each of the column's rows once, as ADR 0104's plan reads a chunk's identity proxy, and sorts each group's keys, flipped forslice_max(), keeping ties in order. Withwith_ties = TRUEa row takes the rank of the first row it ties with, asvec_rank()'s "min" ties give it, and otherwise its own, as "sequential" ties give it. Each group keeps its rows ranked within the slice's size, ordered by rank and then position.norpropand the group's size whennorpropis a bare number. The plan then calls the size function once for each size the groups have. A classed or ALTREP number, or a size whose computation warns or errors, leaves the groups to the loop.slice_min()andslice_max()also need ADR 0104's checks that the loop'svec_rank()call would give these ranks: the records of the functions it reaches, the routines dtatools captured at load, and the absence of other order or proxy methods.vec_rank()withincomplete = "rank", as the slice calls it, finds no complete rows and calls no equality method, so.order_proxy_admitted()takescomplete = FALSEto leave those methods unchecked. None of the closures the loop calls for a later group may be debugged.Behavior
Results are unchanged. ADR 0120 records the decision. Rowwise data,
slice_sample(),na_rm = TRUE, anorder_bythat is not a column's name, and rows that are not bare integer vectors leave the groups to the loop. A traced or replacedvec_check_size(),which(),order()or%in%sees only the first group's calls, as ADR 0058 allows for helpers whose results the plan reproduces.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 main.
slice_max(b, b2, n = 1, by = caseid)slice_head(b, n = 1, by = caseid)Tests
slice_min()andslice_max()of six Stata numeric columns, with and without ties, seven sizes of both signs, asnandprop, bygroup_by()and byby, 336 cases. The data's 60 groups interleave and hold ties, zeros of both signs, and missing and tagged missing values. Each case must give the same value, warnings and errors with the plan as without it, and the plan must take every one.slice_head()andslice_tail(), 28 cases..drop = FALSE, and leaves these to the loop:na_rm = TRUE, expressions, pronouns, double and string columns, a name that is no column, rowwise and ungrouped data,slice_sample(), a classed proportion whose method reads the current group, an ALTREPnwhose third read errors, and an integer proportion whose product with a size overflows, also underoptions(warn = 2). An order or proxy method in the global environment leaves the groups to the loop, but an equality or comparison method, whichvec_rank()does not call here, does not.vec_rank(), debugs each closure the plan skips, and replaces the routinevec_rank()calls, and checks that the plan declines.