10
votes

Comment écrire une fonction R qui évalue une expression dans un cadre de données

puzzle pour le r cognoscenti: dites que nous avons un cadre de données: xxx

Je sais que nous pouvons faire des choses comme xxx

obtenir un vecteur de résultats.

Mais comment puis-je écrire une fonction qui prend une expression (telle que a ou a> 3 ) et fait la même chose à l'intérieur. C'est à dire. Je veux écrire une fonction fn qui prend une trame de données et une expression comme arguments et renvoie le résultat de l'évaluation de l'expression "dans" la trame de données en tant qu'environnée.

Peu importe que cela sonne bien (je pouvais simplement utiliser avec comme ci-dessus), mais il s'agit simplement d'une version simplifiée d'une fonction plus complexe que j'écris. J'ai essayé plusieurs variantes (en utilisant eval , avec , Envir , substitut , local , etc.) mais aucun d'entre eux ne fonctionne. Par exemple, si je défini fn comme: xxx

i obtenir cette erreur: xxx

Il manque clairement quelque chose de subtil sur les environnements et l'évaluation. Y a-t-il un moyen de définir une telle fonction?


5 commentaires

Il y a une section sur Wiki Hadley à propos de ce sujet


@Marek c'est une grande référence à lire, merci!


Cette page est-elle toujours accessible?


Y a-t-il quelque chose qui ne va pas avec juste: fn <- avec ?


Voici celui du manuel: adv-r.hadley.nz/evaluation.htmlleight/a > (2e édition) et peut-être adv-r.had.co.nz/expressions.html (1ère édition)


4 Réponses :


10
votes

C'est parce que vous ne passez pas d'expression.

Essayez: xxx

un coup d'œil rapide au code source des fonctions utilisant ceci (par exemple, lm ) peut révéler beaucoup plus de choses intéressantes à ce sujet.


4 commentaires

Merci, c'est ce qui me manque! Et oui, j'ai essayé de regarder des fonctions telles que sous-ensemble et d'autres, pour voir comment ils le font, mais ils étaient internes. N'a pas réfléchi à lm , bon point pour référence future.


Je pense que l'utilisation de substitution dans cette situation est plus canonique. Et je ne suis pas sûr que LM est un bon modèle - assurez-vous au moins de lire les règles d'évaluation non standard standard.


@hadley: vrai. Je pensais juste à propos de match.call () et lm () en raison de l'argument data .


@Prasad CHALASANI sous-ensemble n'est pas une fonction interne, écrivez sousset.data.frame dans la console et vous verrez comment cela est fait.



-1
votes

? Dans peut également être d'intérêt. xxx


0 commentaires

11
votes

Le package de réseau fait ce genre de chose d'une manière différente. Voir, E.G., Lattice ::: xyplot.formula code>.

fn <- function(dat, expr) {
  eval(substitute(expr), dat)
}
fn(df, a)             # 1 2 3 4 5
fn(df, 2 * a + b)     # 3 6 9 12 15


3 commentaires

+1, très gentil (N'a pas pensé de substitut). L'avantage de match.Call est que vous avez tous vos arguments dans une liste commode, c'est pourquoi j'utilise celui-ci de plus souvent. Mais si vous n'avez pas besoin du reste, il est en effet un moyen très gentil et facile.


Existe-t-il un moyen de transmettre plusieurs expressions dans une liste () ou C () et d'évaluer chacune d'une boucle à boucle pour différents cadres de données qui sont également stockés dans une liste? Je veux la même fonctionnalité que je ne peux tout simplement pas le faire fonctionner pour les données de données et les expressions stockées dans la liste.


@ Blind0ne commence une nouvelle question décrivant votre problème exactement. Vous pouvez relier à cette question.



2
votes

Une entrée tardive, mais le datable.table approche et syntaxe semblerait être ce que vous êtes après. C'est exactement comment [. Data.table fonctionne avec le j , i et par arguments.

Si vous en avez besoin dans le formulaire fn (x, expr) , vous pouvez utiliser ce qui suit xxx

je pense qu'il est plus facile d'utiliser dans Formulaire plus natif xxx

et ainsi de suite. Dans l'arrière-plan, il utilise substitut et eval


0 commentaires