Skip to content

Plan seq_along() and length() of a string column - #466

Merged
jbearak merged 5 commits into
mainfrom
claude/seq-strings
Oct 27, 2026
Merged

jbearak merged 5 commits into
mainfrom
claude/seq-strings

Conversation

@jbearak

@jbearak jbearak commented Oct 27, 2026

Copy link
Copy Markdown
Owner

Summary

ADR 0107 plans seq_along(x) in a grouped mutate() and length(x) in a grouped summary, reframe() or mutate() when x is a Stata numeric column. A string column kept the group loop, even after #465 split it into its groups in one native call. Over the 42,739 women in the first 100,000 rows of the India 2021 DHS births file, mutate(b, k = seq_along(caseid), .by = caseid) took about 0.39 seconds.

This PR lets the plans take x when its first chunk is a Stata string with the classes the package gives one, c("dta_string", "vctrs_vctr", "character"), or a character vector without a class. Each later chunk must have the first chunk's classes, the group's size, and a form whose length runs no R code: an ordinary vector or one of the package's owned, compact or metadata proxy strings. ADR 0130 records the details.

Behavior

Values, attributes, ALTREP forms, warnings and errors are unchanged. R dispatches length() for a Stata string, so the plan declines when R would find a length() method for one of its classes, or a default one, from the call's environment or in base's table, and when a column is named for one, as ADR 0107 requires for a Stata numeric. A string column with other classes keeps the loop.

As in ADR 0107, the plan does not prove what it skips, so a traced or replaced mask$with_group() or rlang::eval_tidy() no longer sees a planned expression's later groups.

Timing

Best of three runs in fresh R sessions, in seconds, with the builds interleaved. Before is main at c91ca74, which has #465.

Call Before After Tibble
mutate(b, k = seq_along(caseid), .by = caseid) 0.394 0.160 0.055
summarise(b, k = length(caseid), .by = caseid) 0.501 0.167 0.048
mutate(b, k = length(caseid), .by = caseid) 0.400 0.160 0.056

Most of what remains is the split of the column, which the plan reads to check the chunks.

Tests

  • test-summary-plan.R compares 4 calls with the group loop and counts the planned expressions: seq_along() and length() of a Stata string and of a character vector in mutate() and summarise(), after group_by(), and of a compact string a read gives.
  • It checks that a global length() method for dta_string, vctrs_vctr or character, each calling NextMethod(), keeps the loop, and so does a column of another class.
  • The full suite passes: 170 files, 2,302 tests. The native manifest and repository guard tests pass.
  • Codex review ran two rounds. The first found that the test's length methods broke slicing, so the checks never reached the plan, and that the manifest was stale. This PR fixes both, and the second review is clean.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@jbearak
jbearak merged commit 95adefc into main Oct 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant