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:
.byis_by:and.keep_allis_keepAll:. See Underscored arguments. - Positions are 1-based, as in R:
pull(1)is the first column,pull(-1)the last, andslice(1, 3)the first and third rows of each group. var()isvar_(), becausevaris a reserved word in PHP.variance()is an alias.summarise()andsummarize()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.
_byalso 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.groupsvalue as a second argument. - A phplyr helper such as
mean('x')returns aPhplyr\Vecthat holds aPhibble\Exprtree, 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(...)orlag(...), 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 typedarray, it receives the whole column instead.
From phpstats/phplyr@d319dc5.