Stellen Sie sich ein Tibble vor, bei dem jede Spalte ein Zeichenvektor ist, der viele Werte annehmen kann - sagen wir "A" bis "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Ich möchte eine Funktion erstellen, die einen Spaltennamen als Argument verwendet und diese Spalte neu codiert, sodass jede Antwort "A" zu einer NA wird und der df ansonsten unverändert zurückgegeben wird. Der Grund für das Entwerfen auf diese Weise besteht darin, in eine breitere Pipeline zu passen, die eine Reihe von Operationen unter Verwendung einer bestimmten Spalte ausführt.
Es gibt viele Möglichkeiten, dies zu tun. Aber ich bin daran interessiert zu verstehen, was der beste idiomatische tidy_eval / tidyverse-Ansatz wäre. Erstens muss sich der Name der Frage auf der linken Seite eines mutierten Verbs befinden, daher verwenden wir die Operatoren !!
und :=
entsprechend. Aber was soll man dann auf die rechte Seite stellen?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
Mein erster Gedanke war, dass dies funktionieren würde:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Aber natürlich gibt der Bang-Bang in der Funktion nur die Literalzeichenfolge zurück (z. B. "q1"). Am Ende habe ich einen hackigen Weg eingeschlagen, um auf die Daten auf der rechten Seite zu verweisen, indem ich den Basis-R- [[
Operator verwendet und .
mich auf das Konstrukt von dplyr verlassen habe. Es funktioniert, also habe ich in gewissem Sinne mein zugrunde liegendes Problem gelöst:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Ich bin daran interessiert, Feedback von Leuten zu erhalten, die sehr gut in Tidyeval sind, ob es einen idiomatischeren Weg gibt, dies zu tun, in der Hoffnung, dass ein funktionierendes Beispiel mein Verständnis der Tidyeval-Funktion allgemeiner verbessern würde. Irgendwelche Gedanken?
q1
(Symbol) als auch mit"q1"
(Zeichenfolge) funktioniert :df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
Antworten:
Hier auf der rechten Seite
:=
können wir angebensym
, dass in ein Symbol konvertiert und dann ausgewertet werden soll (!!
)Ein besserer Ansatz, der sowohl für zitierte als auch für nicht zitierte Eingaben funktioniert, ist
ensym
quelle
Sie können jetzt die Methode "Curly Curly" verwenden, wenn Sie rlang> = 0.4.0 haben .
Erklärung dank @ eipi10:
Dies kombiniert den zweistufigen Prozess des Zitierens und Nicht-Zitierens in einem Schritt und
{{question}}
entspricht damit!!enquo(question)
Beachten Sie, dass dies im Gegensatz zum
ensym
Ansatz bei Zeichennamen nicht funktioniert. Schlimmer noch, es macht das Falsche, anstatt nur einen Fehler zu machen.quelle
question
zuerst in ein Quosure (question = enquo(question)
) umgewandelt werden muss, bevor er in der Dplyr-Pipe verwendet wird.{{question}}
ist äquivalent zu!!enquo(question)
.Sie können die Funktion etwas flexibler gestalten, indem Sie auch die Eingabe eines Vektors mit neu codierten Werten als Argument zulassen. Zum Beispiel:
Beachten Sie, dass
recode.vec
mit "unquote-gespleißt" ist!!!
. Sie können sehen, was dies mit diesem Beispiel tut, angepasst an die Programmierung mit dplyr-Vignette (suchen Sie nach "Spleiß", um die relevanten Beispiele zu sehen). Beachten Sie, wie!!!
die Paare von Rekodierungswerten in dierecode
Funktion "gespleißt" werden, damit sie als...
Argument in verwendet werdenrecode
.Wenn Sie die Rekodierungsfunktion möglicherweise für mehrere Spalten ausführen möchten, können Sie sie in eine Funktion umwandeln, die nur einen Spaltennamen und einen Rekodierungsvektor verwendet. Dieser Ansatz scheint pfeifenfreundlicher zu sein.
Oder um eine einzelne Spalte neu zu codieren:
quelle