phplyr

Reference

Grouping

group_by() sets the grouping columns. Selectors work, named arguments group by a computed column, and _add: true adds to the existing groups. _drop: false keeps groups for unused factor levels, so summarize() and count() return them with n() = 0, as dplyr does. ungroup() removes grouping, or only the named columns.

Groups are ordered like dplyr’s: sorted by key, factors by level order, and NA last. filter(), mutate(), summarize(), and the slice functions work within groups. _by: groups for a single call and returns an ungrouped table.

$schools = DataFrame::fromCsv('schools.csv') |> group_by('school');

echo json_encode([
    'groups' => $schools |> group_vars(),
    'n_groups' => $schools |> n_groups(),
    'sizes' => \array_slice($schools |> group_size(), 0, 4),
]), "\n\n";

// Grouped mutate: helpers are evaluated within each group.
echo $schools |>
    mutate(centered: fn ($r, $g) => round($r->score - mean('score')($g), 2), rank_in_school: min_rank(desc('score'))) |>
    ungroup() |>
    head(4);

// One table per group.
$parts = $schools |> group_split();
echo "\n", \count($parts), ' tables; the first has ', $parts[0]->nrow(), " rows\n";
$schools = phplyr(DataFrame::fromCsv('schools.csv'))->groupBy('school')->get();

echo json_encode([
    'groups' => phplyr($schools)->groupVars(),
    'n_groups' => phplyr($schools)->nGroups(),
    'sizes' => \array_slice(phplyr($schools)->groupSize(), 0, 4),
]), "\n\n";

// Grouped mutate: helpers are evaluated within each group.
echo phplyr($schools)
    ->mutate(centered: fn ($r, $g) => round($r->score - mean('score')($g), 2), rank_in_school: min_rank(desc('score')))
    ->ungroup()
    ->head(4);

// One table per group.
$parts = phplyr($schools)->groupSplit();
echo "\n", \count($parts), ' tables; the first has ', $parts[0]->nrow(), " rows\n";
{"groups":["school"],"n_groups":12,"sizes":[18,24,15,22]}

# A tibble: 4 × 6
  school    study_hours prior_score score centered rank_in_school
  <chr>           <dbl>       <dbl> <dbl>    <dbl>          <int>
1 school-01       11.6         77.3  78.3     5.34              4
2 school-01        2.7         51.7  67.2    -5.67             14
3 school-01       10.0         78.8  88.2    15.3               2
4 school-01        3.71        45.3  68.5    -4.37             13
12 tables; the first has 18 rows

Group utilities

Function Returns
group_vars() The grouping column names
n_groups() The number of groups
group_size() Rows per group
group_indices() Each row’s 1-based group number
group_keys() A table of group keys
group_rows() Each group’s 1-based row numbers
group_data() The group keys with a .rows list-column
group_trim() The table regrouped without unused factor levels
group_nest(_key:, _keep:) One row per group, with a list-column of tables
nest_by(...cols) group_nest() as a rowwise table
with_groups(_groups, fn) The function’s result under other groups, with the original grouping restored
group_split(_keep:) A list of tables, one per group
group_map(fn ($table, $key)) A list of the function’s results
group_modify(fn ($table, $key)) A grouped table built from the returned tables
group_walk(fn ($table, $key)) The table, after calling the function per group
group_cols() A selector for the grouping columns
cur_group_id() The current group’s number, in mutate(), summarize(), and reframe()
cur_group_rows() The current group’s row numbers, in mutate() and reframe()
cur_group() The current group’s key as an array of column => value

Row-wise operations

rowwise() makes each row its own group. Closures in summarize() and vector helpers then see one row at a time. Optional id columns stay as groups in the result of summarize(). c_across(cols) gives the current row’s values of the selected columns, for helpers such as sum(c_across(starts_with('x'))).

echo DataFrame::fromRows([
    ['id' => 'a', 'q1' => 3, 'q2' => 5, 'q3' => null],
    ['id' => 'b', 'q1' => 4, 'q2' => 1, 'q3' => 2],
]) |>
    rowwise('id') |>
    summarize(total: fn ($row) => Stats::sum(
        [...$row->column('q1'), ...$row->column('q2'), ...$row->column('q3')],
        naRm: true,
    ));
echo phplyr(DataFrame::fromRows([
    ['id' => 'a', 'q1' => 3, 'q2' => 5, 'q3' => null],
    ['id' => 'b', 'q1' => 4, 'q2' => 1, 'q3' => 2],
]))
    ->rowwise('id')
    ->summarize(total: fn ($row) => Stats::sum(
        [...$row->column('q1'), ...$row->column('q2'), ...$row->column('q3')],
        naRm: true,
    ));
# A tibble: 2 × 2
# Groups:   id [2]
  id    total
  <chr> <int>
1 a         8
2 b         7

From phpstats/phplyr@d319dc5.