Resources

Lionel Henry | Working with names and expressions in your tidy eval code | RStudio (2019)

n practice there are two main flavors of tidy eval functions: functions that select columns, such as `dplyr::select()`, and functions that operate on columns, such as `dplyr::mutate()`. While sharing a common tidy eval foundation, these functions have distinct properties, good practices, and available tooling. In this talk, you'll learn your way around selecting and doing tidy eval style. Materials: https://speakerdeck.com/lionelhenry/selecting-and-doing-with-tidy-eval

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Aujourd'hui, je vais parler de la sélection et de l'utilisation de TidyEval. L'objectif sera de créer une fonction autour des pipelines de TidyEval et de vous montrer la façon la plus facile de faire cela. Jenny a montré un peu, c'est de passer les points à travers les fonctions de TidyEval. Et nous allons nous concentrer sur deux goûts de TidyEval, la sélection et l'utilisation.

Pour revenir sur la raison pour laquelle nous avons TidyEval, pour le mettre en plus de contexte, l'objectif est vraiment de changer le contexte de la computation. Par exemple, si nous avons cette fonction de filtre, où vous passez un cadre de données et des expressions de filtre, nous voulons prendre ces expressions et les évaluer dans le contexte du cadre de données.

Vous avez donc le code de base équivalent sur le côté droit, où vous devez être spécifique pour savoir d'où viennent les colonnes. Cela va encore plus loin, car nous pouvons changer le contexte de la computation à l'aide d'un database étranger, et nous pouvons traduire vos expressions de filtre dans une enquête SQL.

Nous avons donc besoin de TidyEval pour cela, car si nous utilisions des fonctions normales, vous obtiendriez cette erreur d'objet not found, car R ne sait pas d'un objet de hauteur.

C'est pour cela que nous avons besoin de dépasser la computation de ces expressions. Nous devons éviter l'évolution. C'est ce que nous voulons par le codage. Le codage signifie que nous dépassons la computation, puis nous changeons le contexte et nous résumons la computation.

Le code de codage est un peu comme un blueprint pour la computation. Il nous dit ce qu'il faut faire pour obtenir un résultat. Quand nous avons un code codé comme celui-ci, lorsque vous programmez contre des fonctions qui travaillent sur des blueprints, vous devez modifier les blueprints. C'est pour cela que nous avons BangBang, qui est un opérateur de chirurgie pour les blueprints.

C'est pour cela que nous avons BangBang, qui est un opérateur de chirurgie pour les blueprints.

Les deux goûts de TidyEval : sélection et action

Nous allons parler des deux goûts de TidyEvaluation que nous avons dans Tidyverse. Nous avons ici quatre fonctions de dplyr, Mutate, GroupBy, Select et Filter. Elles ressemblent un peu à celles-ci. Elles sont utilisées de la même manière. Mais il y en a une qui est différente des autres. C'est Select. Select prend une sélection. Toutes les autres fonctions prennent des actions.

Ce que nous voulons par action, c'est que nous obtenions ce blueprint et qu'on l'utilise pour créer de nouveaux vecteurs. Ensuite, nous modifions le cadre de données. Par contre, avec la sélection, quelque chose de différent s'est produit. Nous avons matché les colonnes à leur position dans le cadre de données et nous avons réorganisé le cadre de données. Il n'y a pas de création de vecteurs.

Dans les actions, quand nous obtenons le blueprint, c'est un code R normal. Mais dans la sélection, il y a quelques fonctions spéciales. Pour commencer, la fonction C et les opérateurs de colonnes et de minus comprennent les positions et les noms des colonnes. C'est ainsi que vous pouvez très facilement spécifier un rang de colonnes. Par exemple, avec l'opérateur de colonnes.

Vous pouvez aussi utiliser les opérateurs de sélection, qui sont très utiles car ils connaissent les variables avec lesquelles vous travaillez actuellement. Par exemple, vous pouvez sélectionner toutes les colonnes qui finissent avec une suffixe, ou vous pouvez les matcher contre un ragaphone. C'est très utile quand vous avez des frames de données bien organisées avec des noms de colonnes consistants avec des suffixes et des préfixes. Cela fait très facile de sélectionner les colonnes.

Parfois, les verbes d'action et de sélection apparaissent fonctionner de la même façon. Ici, nous avons Select Height et Transmute Height. Et nous obtenons exactement le même résultat. Mais c'est utile de savoir si vous avez un verbe d'action ou un verbe de sélection, car si vous changez un peu l'entrée, ici, je supplie un.

Pour le verbe de sélection, puisqu'il comprend les positions des colonnes, il signifie sélectionner la première colonne. Pour le verbe d'action, il créera un nouveau vecteur de votre entrée. Dans ce cas-ci, on le recycle pour la taille de la frame de données et on obtient une colonne d'un seul.

Le cas de Group By

Qu'est-ce qu'il y a de Group By ? C'est un cas intéressant, car la plupart des utilisateurs pensent que c'est un verbe de sélection. Mais en réalité, c'est un verbe d'action. Si vous essayez de passer un groupe de sélection, vous obtiendrez cette erreur où les variables ne sont pas trouvées.

Nous l'avons fait un verbe d'action car c'est très utile pour créer ces nouveaux vecteurs sur la flèche où vous discriminez entre les groupes. Dans cet exemple, je groupe par les observations dont la taille est au-dessus d'un certain threshold. Ensuite, je les résume sur la flèche et j'obtiens un bon tableau de résumés.

Qu'est-ce que vous pouvez faire si vous avez un verbe d'action comme Group By et que vous voulez vraiment passer une sélection ? Vous pouvez utiliser les variants At, les verbes scopés. Nous avons MutateAt, SummarizeAt, GroupByAt et un tas d'autres.

Ils prennent une sélection à l'intérieur de cette petite fonction Vars qui est une fonction qui fait le coding, qui obtient le blueprint et qui le passe au GroupByAt. Au-delà de ça, vous pouvez passer une sélection. Ici, dans cet exemple, nous groupons par toutes les colonnes qui finissent avec couleur.

Créer des fonctions TidyEval avec le dot

Voyons donc comment nous pouvons créer des valeurs idéales. Il y a trois défis ici. D'abord, il y a la nécessité de coder les entrées pour obtenir les sélections et les actions des utilisateurs. Ensuite, il y a la nécessité de modifier ces sélections ou actions et de les passer vers d'autres valeurs idéales.

La deuxième est plus complexe que la première. C'est là que vous devez comprendre toute la théorie idéale. Vous devez utiliser les outils idéaux comme Bang Bang. Nous ne parlons pas de ça. Aujourd'hui, nous allons nous concentrer sur les premières et les troisièmes défis. Pour ce faire, nous allons passer le dot.

Ici, nous avons la fonction la plus simple que vous pouvez créer en passant le dot. Nous prenons typiquement un frame de données, puis nous prenons le dot, et nous le passons à une autre fonction idéale. Cela signifie que tous les arguments que l'utilisateur apporte à travers le dot sont maintenant la responsabilité de nos fonctions dans dplyr, Tidyer ou les autres grammaires Tidyverse pour faire le codage et créer les actions ou les sélections. Vous n'avez donc pas à faire quelque chose et vous réservez les deux défis 1 et 3 en même temps.

C'est un peu limité, mais ça peut être très utile et nous allons voir trois exemples. D'abord, nous allons créer un verbe de sélection avec dplyr. Ensuite, nous allons voir comment nous pouvons transformer ce verbe de sélection en un verbe d'action. Ensuite, nous allons utiliser Tidyer pour complexifier le pipeline.

Comme je l'ai mentionné, la plupart des verbes de dplyr ont une suffixe variante avec un at, et ils prennent des sélections, ce qui peut être très utile pour voir si vous voulez créer un verbe de sélection en passant le dot.

Deux d'entre eux sont un peu différents des autres parce qu'ils prennent une sélection, mais ils prennent aussi une fonction. Ils appliquent la fonction à chaque colonne qui fait partie de la sélection. C'est un peu comme l'application L ou la mappage de la fonction par.

Ça marche comme ça. Vous passez un frame de données, vous passez une sélection, c'est comme ça, et puis une fonction qui peut aussi être par lambda, avec la notation de la formule. Ça applique le corps de la fonction à chaque colonne de la sélection, et c'est comme si vous aviez créé cet enregistrement plus long.

Ça peut prendre une fonction, une seule fonction, mais ça peut aussi prendre une liste de fonctions. Ici, je crée une liste avec une fonction qui prend l'égalité et ensuite la déviation standard. Quand vous passez une liste de fonctions, vous appuyez sur chaque colonne à chaque colonne et vous distribuez les résultats à travers les colonnes.

Exemple : Summarize Cells

Notre première fonction à haut niveau sera appelée Summarize Cells pour les sélections. Nous nous enroules autour de Summarize At, nous passons les doigts à Vars, nous passons la liste de fonctions de résumé à elle, et vous pouvez l'utiliser en passant les sélections. Et vous obtenez la liste de résumés.

Ce qui est agréable, c'est qu'elle fonctionne avec des groupes. C'est toujours une bonne idée de penser à ce qui se passe quand vous passez une liste de groupe à votre fonction TidyEval. Si vous utilisez les verbes de déployer, et dans ce cas, ça créera les résumés pour chaque groupe.

Alors, qu'est-ce si nous voulions fournir des actions au lieu des sélections ? Quand vous voulez créer un verbe d'action, une fonction très utile pour passer les doigts est Transmute, parce que c'est comme le verbe d'action fondamental dans le joueur. Il prend des actions, il crée des vecteurs de ces actions, et il vous retourne la table qui contient ces vecteurs.

Au dessus, vous avez l'implémentation précédente des cellules de résumé, et maintenant nous avons la nouvelle fonction SummarizeAt, et nous passons les doigts à Transmute. Et au lieu d'utiliser SummarizeAt, nous utilisons SummarizeAll, qui appliquera les fonctions de résumé sur toutes les colonnes de la table qui est passée. Et ça vous donne une fonction d'action et vous pouvez créer de nouveaux vecteurs dans l'entrée, comme dans Mutate ou Table.

Ici, j'essaie de calculer un BMI, mais je n'ai pas une hauteur correcte, donc je peux passer une première action qui crée une hauteur en mètres, et puis je peux calculer le BMI avec ça. Et ça crée les summaries pour les deux vecteurs.

Et ça fonctionne encore avec les groupes.

Rassembler les résultats avec TidyR Gather

Donc, cette table avec les résultats diffusés à travers les colonnes n'est pas si propre, alors qu'est-ce si nous voulions les rassembler à travers les lignes ? Donc, c'est évidemment un travail plus propre, et nous allons ajouter une étape de rassemblage à notre pipeline. Et nous verrons que gérer les groupes sera un peu plus compliqué dans ce cas.

Donc, c'est comme ça. Nous passons encore les points de transmutation, mais maintenant, nous rassemblons toutes les colonnes créées avec Transmute, avec la fonction TidyRGather. Nous groupons par la variable et nous appliquons les fonctions de résumé sur la valeur de la colonne. Et ça vous donne une table beaucoup plus jolie.

Le problème, c'est qu'ici, ça ne fonctionne pas avec les groupes. C'est pour ça que c'est toujours une bonne idée, quand vous créez une nouvelle fonction, de voir ce qui se passe quand vous passez une table de données groupée. Et la raison est qu'il faut aussi rassembler les variables groupées et vous ne pouvez pas appliquer les résumés sur ces variables groupées sans avoir ces erreurs.

Donc, la façon de le réparer est très simple. Nous rassemblons tout, sauf les variables groupées. Et maintenant, ça marche. Et nous avons cette jolie table de résumés.

Pour finir, passer les points est peut-être la façon la plus simple de créer une fonction TidyRGather. Quand vous créez une fonction, c'est bien de penser à savoir si vous avez besoin d'un verbe d'action ou d'un verbe de sélection, et puis vous pouvez utiliser la variable At si vous avez besoin de sélection, ou d'autres fonctions TidyRGather.

Si vous passez les points, c'est une fonction qui prend des sélections, ça signifie que votre réparateur prend aussi des sélections. Donc, il faut connaître les verbes TidyRGather pour pouvoir créer le pipeline adéquat, mais c'est une connaissance que vous êtes déjà familière avec, et si vous apprenez de nouvelles choses, c'est adaptable à votre travail quotidien. Et enfin, c'est toujours une bonne idée de penser à la table de données groupée parce qu'elle vous donne des résultats utiles quand vous avez besoin de compter des choses en groupe.

Donc, mes slides sont sur le deck de paroles, et merci.

Questions

Nous avons du temps pour plusieurs questions, si vous n'avez pas de questions, vous pouvez poser vos mains, et on vous mettra quelque chose.

J'ai une question sur la table de données groupée que vous avez résumée par rangs. Celle-ci? Oui. Alors, où dans cette fonction est-ce qu'elle le fait par rangs? C'est parce que vous rassemblez tous les nouveaux vecteurs que vous créez avec les inputs de l'utilisateur, et puis on les groupe par les variables. Et puis les summaries de SummarizeAt s'appliquent pour chaque groupe des variables qui ont été créées dans les points. Merci.