2
votes

Évaluation non standard de la condition de date avec fonction de filtre

J'essaie d'utiliser dplyr :: filter () avec NSE, mais je ne peux pas le faire fonctionner lorsque la variable filtrée est as.Date () .

Voici la fonction qui fonctionne presque:

foo2 <- function(d, f, var) {
  d %>% 
    filter(!!var >= f)
}
#foo2(d, f=5, var="a")
#foo2(d, f="2019-01-05", var="a")

Mais si a est une date ça ne fonctionnera pas:

XXX

J'ai également essayé ceci:

d <- data.frame(a=seq.Date(as.Date("2019-01-01"), length.out = 7, by="day"), b=1)

foo(d, f=as.Date("2019-01-05"), var="a") # or foo(d, f="2019-01-05", var="a")
#            a b
# 1 2019-01-01 1
# 2 2019-01-02 1
# 3 2019-01-03 1
# 4 2019-01-04 1
# 5 2019-01-05 1
# 6 2019-01-06 1
# 7 2019-01-07 1

Ce qui ne fonctionne pas dans les deux cas, je suis intéressé de savoir pourquoi foo2 cela ne fonctionne pas.


2 commentaires

Puisque vous passez le nom de la variable sous forme de chaîne, vous voudrez quelque chose comme ensym () autour de var dans votre fonction. Comme var = ensym (var) avant la ligne filter () . Ensuite, les choses devraient fonctionner pour les dates si vous passez f une valeur via as.Date () .


Merci, cela fonctionne avec foo2 , voulez-vous publier comme réponse?


3 Réponses :


1
votes

Vous n'avez pas besoin de !! ( rlang :: ). Insérez var dans as.name (ou as.symbol ) pour en faire un symbole, puis utilisez eval () code > à l'intérieur du filtre pour évaluer l'objet dans l'environnement de la fonction:

> foo2(d, f="2019-01-05", var="a")
           a b
1 2019-01-05 1
2 2019-01-06 1
3 2019-01-07 1

Résultat:

library(magrittr)
library(dplyr)    

d <- data.frame(a=seq.Date(as.Date("2019-01-01"), length.out = 7, by="day"), b=1)

foo2 <- function(d, f, var) {
  sym <- as.name(var)

  d %>% 
    filter(eval(sym) >= f)
}


0 commentaires

1
votes

essayez de transmettre l'argument var pas comme une chaîne. dans ce cas, vous devez changer la fonction foo en:

foo <- function(d, f, var) {
   var <- enquo(var)
   d %>% 
      filter(!!var >= f)
}
foo(d, f=as.Date("2019-01-05"), var=a)


0 commentaires

1
votes

Ne modifiez pas votre fonction. Concentrons-nous sur le code

foo(d, f = unclass(as.Date("2019-01-05")), var = "a")

#            a b
# 1 2019-01-05 1
# 2 2019-01-06 1
# 3 2019-01-07 1

Si l'entrée f est une Date , l'instruction paste0 (var, "> = ", f) dans votre fonction renverra

" a> = 2019-01-05 " (Cela signifie la colonne a est supérieur et égal à "2019-01-05" , qui est une chaîne de caractères et non une date car les sorties de paste () sont toujours des caractères)

L'instruction ci-dessus n'est pas significative car les chaînes de caractères ne peuvent pas être comparées. Vous devez donc transformer la date d'entrée en numérique par unclass () ou as.numeric () tel que

foo(d, f = unclass(as.Date("2019-01-05")), var = "a")

et l'instruction renverra "a> = 17901" , qui est une instruction logique normale.


Sortie

foo(d, f = as.Date("2019-01-05"), var = "a")

Notez que "a> = 17901" réussira car les dates (colonne a ) peuvent être par rapport aux chiffres ( 17910 ).


0 commentaires