phplyr

Guides

Coming from dplyr

phplyr keeps dplyr’s and tidyr’s function names, argument names, and results. This page lists the differences that come from PHP syntax. Compatibility and limitations lists the dplyr features phplyr does not have.

Syntax translation

In R, functions are chained with %>% or |>. In PHP 8.5, they are chained with |>. On PHP 8.3 and 8.4, they are methods of a chain: phplyr($t)->filter(...)->arrange(...). The table below shows single calls.

dplyr phplyr
filter(x > 1) filter(fn ($r) => $r->x > 1)
mutate(z = x * 2) mutate(z: fn ($r) => $r->x * 2) or mutate(z: col('x')->mul(2))
mutate(z = lag(x)) mutate(z: lag('x'))
summarise(m = mean(x, na.rm = TRUE)) summarize(m: mean('x', naRm: true))
select(-id) select(except('id'))
select(new = old, everything()) select(['new' => 'old'], everything())
rename(new = old) rename(new: 'old')
arrange(desc(x)) arrange(desc('x'))
mutate(..., .by = g) mutate(..., _by: 'g')
summarise(..., .groups = "drop") summarize(..., _groups: 'drop')
across(c(a, b), mean) across(['a', 'b'], mean(...))
across(c(a, b), \(x) x * 2) across(['a', 'b'], fn ($x) => $x * 2)
case_when(x < 0 ~ "neg", .default = "pos") case_when([fn ($r) => $r->x < 0, 'neg'], default: 'pos')
left_join(y, by = c("a" = "b")) left_join($y, by: ['a' => 'b'])
left_join(y, by = join_by(a)) left_join($y, by: 'a')
join_by(id, t >= start) join_by('id', col('t')->ge(col('start')))
join_by(closest(t >= start)) join_by(closest(col('t')->ge(col('start'))))
pivot_longer(-id) pivot_longer(except('id'))
var(x) var_('x')
NA null

Conventions

  • Dot-arguments keep the dot as a leading underscore, and a multi-word name is camelCase after it: .by is _by: and .keep_all is _keepAll:. See Underscored arguments.
  • Positions are 1-based, as in R: pull(1) is the first column, pull(-1) the last, and slice(1, 3) the first and third rows of each group.
  • var() is var_(), because var is a reserved word in PHP. variance() is an alias.
  • summarise() and summarize() are the same function, as in dplyr.
  • count(), min(), max(), rename(), and other functions have the names of PHP built-ins. In a file that imports them, write \count() for the built-in. Imports lists them.
  • Group order follows dplyr: groups are sorted by key, factors by level order, and NA last. _by also sorts groups (dplyr keeps first-appearance order for .by).

Underscored arguments

phplyr’s parameters are camelCase, like the rest of the phpstats family. Every argument that dplyr or tidyr writes with a dot keeps it here as a leading underscore, and a multi-word name is camelCase after the underscore. There are sixteen options. recode() also names its first parameter $_x, after dplyr’s .x:

phplyr dplyr / tidyr On
_by .by filter(), filter_out(), mutate(), transmute(), summarise(), reframe(), slice(), the slice_*() family, group_split()
_keep .keep mutate(), group_nest(), nest_by(), group_split(), group_map()
_keepAll .keep_all distinct()
_groups .groups summarise(), with_groups()
_before .before mutate(), relocate(), add_row()
_after .after mutate(), relocate(), add_row()
_add .add group_by()
_drop .drop group_by()
_byGroup .by_group arrange()
_key .key group_nest(), nest_by()
_id .id bind_rows(), uncount()
_remove .remove hoist(), uncount()
_direction .direction fill()
_namesSep .names_sep pack()
_default .default recode()
_missing .missing recode()
$_x .x recode()

Most of the verbs that take one are variadic. A named argument to a variadic function lands in the same string-keyed array as the columns the call creates, so without the prefix the option would always win and a column of that name would be unreachable. dplyr and tidyr use the dot for the same reason. With the prefix, both work:

$t |> mutate(m: mean('x'), _by: 'g');
$t |> mutate(by: 1);
phplyr($t)->mutate(m: mean('x'), _by: 'g');
phplyr($t)->mutate(by: 1);

The first call computes m within each group of g. The second makes a column called by.

The prefix is the only spelling an option has. An unprefixed named argument is always data, so mutate(before: 'id') makes a column called before rather than placing the new columns. A prefixed name that is not an option for that verb is an error naming the ones that are.

Every other argument is camelCase, as in the rest of the phpstats packages. dplyr and tidyr write these without a dot: naRm:, orderBy:, namesFrom:, namesTo:, withTies:, and the rest.

phplyr options and phibble methods

phplyr functions and phibble methods both take and return phibble tables, so a pipeline can use both. phibble’s methods have their own conventions:

  • A phibble method takes an array: $df->mutate(['z' => $expr]), $df->groupBy(['g']), $df->arrange([['x', 'desc']]). A phplyr function takes named arguments: mutate(z: ...), group_by('g'), arrange(desc('x')).
  • phibble methods have no underscored options. Grouping is a separate method call, and summarise(array $aggregates, ?string $groups) takes the .groups value as a second argument.
  • A phplyr helper such as mean('x') returns a Phplyr\Vec that holds a Phibble\Expr tree, the kind phibble’s expression functions build. phplyr passes the tree to the table. A database table compiles it to SQL where a translation exists and otherwise loads the rows and evaluates it in PHP, as Databases and expressions describes.

across() functions

R passes a vector to every across() function. PHP closures have no such convention, so phplyr decides what a function receives:

  • A phplyr helper passed as a first-class callable, such as mean(...) or lag(...), is called with each column’s name.
  • In summarize(), any other closure receives the column’s values as a list.
  • In mutate(), a closure receives one value at a time. If its first parameter is typed array, it receives the whole column instead.

From phpstats/phplyr@d319dc5.