Rozważmy tabliczkę, w której każda kolumna jest wektorem znaków, który może przyjmować wiele wartości - powiedzmy „A” do „F”.
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Chciałbym utworzyć funkcję, która przyjmuje nazwę kolumny jako argument i koduje tę kolumnę tak, aby każda odpowiedź „A” stała się NA, a plik df jest zwracany w niezmienionej postaci. Powodem zaprojektowania go w ten sposób jest dopasowanie do szerszego potoku, który wykonuje szereg operacji przy użyciu danej kolumny.
Istnieje wiele sposobów, aby to zrobić. Ale jestem zainteresowany zrozumieniem, jakie byłoby najlepsze idiomatyczne podejście tidy_eval / tidyverse. Po pierwsze, nazwa pytania musi znajdować się po lewej stronie zmutowanego czasownika, więc używamy odpowiednio operatorów !!
i :=
. Ale co umieścić po prawej stronie?
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")
Początkowo myślałem, że to zadziała:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Ale oczywiście bang-bang wewnątrz funkcji po prostu zwraca dosłowny ciąg znaków (np. „Q1”). Skończyło się na czymś, co wydaje się hacką trasą, aby odwoływać się do danych po prawej stronie, używając podstawowego [[
operatora R i polegając na .
konstrukcji z dplyr, i działa, więc w pewnym sensie rozwiązałem swój podstawowy problem:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Jestem zainteresowany otrzymywaniem opinii od ludzi, którzy są bardzo dobrzy w tidyeval na temat tego, czy istnieje bardziej idiomatyczny sposób, aby to zrobić, w nadziei, że zobaczenie działającego przykładu poprawi moje rozumienie ogólnie ustawionej funkcji tidyeval. jakieś pomysły?
q1
(symbolem), jak i"q1"
(ciągiem):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
Odpowiedzi:
Tutaj, po prawej stronie
:=
, możemy określićsym
konwersję na symbol, a następnie ocenę (!!
)Lepszym podejściem, które sprawdzałoby się zarówno w przypadku cytowania, jak i cytowania, jest
ensym
źródło
Możesz teraz użyć metody „curly curly”, jeśli masz rlang> = 0.4.0 .
Wyjaśnienie dzięki @ eipi10:
Łączy to dwuetapowy proces cytowania, a następnie wycofywania w jednym kroku, więc
{{question}}
jest to równoważne z!!enquo(question)
Zauważ, że w przeciwieństwie do
ensym
podejścia, nie działa to z nazwami postaci. Co gorsza, robi coś złego zamiast po prostu dawać błąd.źródło
question
najpierw musi zostać zamieniony w quosure (question = enquo(question)
), zanim zostanie użyty w rurze dplyr.{{question}}
jest równoważne z!!enquo(question)
.Możesz uczynić tę funkcję nieco bardziej elastyczną, pozwalając również na wprowadzenie wektora przekodowanych wartości jako argumentu. Na przykład:
Zauważ, że
recode.vec
jest to „bez cudzysłowu”!!!
. Możesz zobaczyć, co to robi z tym przykładem, zaadaptowanym z programowania z winietą dplyr (wyszukaj „splice”, aby zobaczyć odpowiednie przykłady). Zwróć uwagę, jak!!!
„splata” pary wartości przekodowywania dorecode
funkcji, aby były one używane jako...
argument wrecode
.Jeśli chcesz potencjalnie uruchomić funkcję przekodowywania na wielu kolumnach, możesz przekształcić ją w funkcję, która pobiera tylko nazwę kolumny i wektor przekodowywania. Takie podejście wydaje się być bardziej przyjazne dla rur.
Lub, aby przekodować jedną kolumnę:
źródło