pick, pluck, pull expliqués à ma fille
On dirait une comptine pour enfants… J’ai voulu expliquer trois fonctions aux noms cryptiques de {tidyverse} : pick, pluck et pull. J’espère que vous n’allez pas vous endormir avant la fin de l’histoire (spoiler : elle finit bien).
Pick
La fonction dplyr::pick est une alternative au across quand il n’a qu’un seul argument (pour plus d’infos sur across : voir ici). Par exemple dans les calculs “horizontaux” avec des fonctions comme rowSums.
library(dplyr)
mtcars %>%
mutate(total = rowSums(pick(where(is.numeric))),
.before = everything())
total mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 328.980 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 329.795 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 259.580 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 426.135 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 590.310 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 385.540 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 656.920 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 270.980 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 299.570 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Merc 280 350.460 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 349.660 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Merc 450SE 510.740 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 511.500 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 509.850 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 728.560 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 726.644 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 725.695 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 213.850 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 195.165 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 206.955 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 273.775 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Dodge Challenger 519.650 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 506.085 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Camaro Z28 646.280 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Pontiac Firebird 631.175 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 208.215 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 272.570 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 273.683 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 670.690 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 379.590 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 694.710 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 288.890 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
# même résultat avec across au lieu de pick
mtcars %>%
mutate(total = rowSums(across(where(is.numeric))),
.before = everything())
total mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 328.980 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 329.795 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 259.580 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 426.135 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 590.310 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 385.540 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 656.920 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 270.980 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 299.570 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Merc 280 350.460 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 349.660 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Merc 450SE 510.740 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 511.500 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 509.850 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 728.560 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 726.644 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 725.695 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 213.850 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 195.165 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 206.955 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 273.775 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Dodge Challenger 519.650 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 506.085 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Camaro Z28 646.280 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Pontiac Firebird 631.175 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 208.215 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 272.570 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 273.683 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 670.690 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 379.590 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 694.710 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 288.890 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
Comme across on peut également s’en servir dans group_by ou arrange pour intégrer des paramètres qui listent des noms de colonnes sous forme de vecteurs texte.
colonnes <- c("am","vs")
mtcars %>%
group_by(pick(all_of({{colonnes}}))) %>%
count() %>%
ungroup()
# A tibble: 4 × 3
am vs n
<dbl> <dbl> <int>
1 0 0 12
2 0 1 7
3 1 0 6
4 1 1 7
Enfin pick peut servir à utiliser des fonctions comme starts_with, ends_with, contains ou where dans des contextes où elles ne sont pas les bienvenues comme dans count, group_by ou arrange. Là encore, across rend le même service.
try(
mtcars %>%
arrange(starts_with("h"))
) # ne fonctionne pas
Error in arrange(., starts_with("h")) :
ℹ In argument: `..1 = starts_with("h")`.
Caused by error:
! `starts_with()` must be used within a *selecting* function.
ℹ See <https://tidyselect.r-lib.org/reference/faq-selection-context.html> for
details.
mtcars %>%
arrange(pick(starts_with("h"))) # trie selon "hp"
mpg cyl disp hp drat wt qsec vs am gear carb
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
mtcars %>%
arrange(across(starts_with("h"))) # fonctionne aussi
mpg cyl disp hp drat wt qsec vs am gear carb
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Pluck
La fonction pluck se trouve dans le package {purrr} intégré à {tidyverse}. Son rôle est de renvoyer un élément de liste, repéré par un numéro ou un nom, comme peuvent le faire les syntaxes de R base [[ ou $.
library(purrr)
mtcars %>%
pluck("cyl") # récupère la colonne "cyl" en tant que vecteur, comme avec mtcars$cyl
[1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
Cette fonction s’avère plus spécialement utile sur une sortie de fonction statistique car ce sont souvent des listes avec une structure complexe.
t.test(mtcars$hp, mu=100) %>%
pluck("p.value") # équivaut à t.test(...)$p.value
[1] 0.0005502226
Dans les structures imbriquées, on énumère les différents noms ou indices des éléments à récupérer à la suite les uns des autres, séparés par des virgules.
lapply(mtcars, t.test, mu=100) %>%
pluck("hp","p.value") # équivaut à lapply(mtcars, t.test)$hp$p.value
[1] 0.0005502226
Pull
La fonction dplyr::pull permet de récupérer une colonne sous forme de vecteur. En effet, une syntaxe comme select renvoie toujours un data.frame, même s’il ne contient qu’une seule colonne. Alors que pour créer un paramètre ou piloter une boucle, c’est souvent un vecteur qui est demandé.
Comme on vient de le voir, purrr::pluck rend également ce service, avec un usage plus général, puisqu’il s’applique à une liste en général. pull s’applique uniquement à des data.frames.
mtcars %>%
distinct(cyl) %>%
pull()
[1] 6 4 8
# en R base
unique(mtcars$cyl)
[1] 6 4 8
# sans pull() le résultat est un data.frame à 1 colonne
mtcars %>%
distinct(cyl)
cyl
Mazda RX4 6
Datsun 710 4
Hornet Sportabout 8
En revanche, pull pourra s’appliquer à un lazy data.frame comme ce que renvoie la fonction tbl qui manipule des liens vers des tables dans des bases de données.
library(duckdb)
bd <- dbConnect(duckdb())
duckdb_register(bd, "table_mtcars", mtcars)
lien_vers_mtcars <- tbl(bd, "table_mtcars")
lien_vers_mtcars %>%
distinct(cyl) %>%
pull()
[1] 8 4 6
lien_vers_mtcars %>%
distinct(cyl) %>%
pluck(1) # le résultat est différent car la liste contient une requête, pas les données issues de l'exécution de la requête (c'est une lazy query)
src: DuckDB 1.4.4 [PC@Windows 10 x64:R 4.5.2/:memory:]
tbls: table_mtcars
Configuration de R pour le code de cet article
sessionInfo()
R version 4.5.2 (2025-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 10 x64 (build 19045)
Matrix products: default
LAPACK version 3.12.1
locale:
[1] LC_COLLATE=French_France.utf8 LC_CTYPE=French_France.utf8
[3] LC_MONETARY=French_France.utf8 LC_NUMERIC=C
[5] LC_TIME=French_France.utf8
time zone: Europe/Paris
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] duckdb_1.4.4 DBI_1.3.0 purrr_1.2.2 dplyr_1.2.1
loaded via a namespace (and not attached):
[1] vctrs_0.7.3 cli_3.6.5 knitr_1.51 rlang_1.2.0
[5] xfun_0.59 otel_0.2.0 generics_0.1.4 jsonlite_2.0.0
[9] glue_1.8.1 dbplyr_2.5.2 htmltools_0.5.8.1 rmarkdown_2.29
[13] evaluate_1.0.5 tibble_3.3.0 fastmap_1.2.0 yaml_2.3.12
[17] lifecycle_1.0.5 compiler_4.5.2 blob_1.2.4 htmlwidgets_1.6.4
[21] pkgconfig_2.0.3 rstudioapi_0.19.0 digest_0.6.37 R6_2.6.1
[25] tidyselect_1.2.1 pillar_1.11.0 magrittr_2.0.3 tools_4.5.2
[29] withr_3.0.3