2017-09-11 4 views
1

Ich versuche, dplyr in der Programmierung zu verwenden: Filterverhalten mit zitierten Variablen sind nicht verständlich. Nach mehreren Versuchen, die realen Daten zu analysieren, hatte ich folgende Dummy-Daten erstellt.dplyr Programmierung: unerwartetes Verhalten des Filters

dt <- data.frame(
    sex = rep(c("F","M"), 50), 
    height = runif(100, 1, 1000), 
    weight = rep(c(2, 100), 50), 
    value = runif(100, 1, 1000), 
    stringsAsFactors = FALSE 
) 



library(dplyr) 


wizzard_fun_1 <- function(param1){ 
    par1 <- enquo(param1) 

dt %>% select(height, !!par1) 
} 

wizzard_fun_1("sex") 

# as expected 
#1 74.875344 F 
#2 846.614856 M 
#..... 


wizzard_fun_2 <- function(param1){ 
    par1 <- enquo(param1) 

    dt %>% select(height, !!par1) %>% 
    filter((!!par1) == 'M') 
} 

wizzard_fun_2('sex') 

#[1] height sex 
# ... zero rows.... 

Was läuft falsch? Vielen Dank im Voraus für irgendwelche Ideen!

+0

See [hier] (https://stackoverflow.com/questions/44121728/programming-with-dplyr-using-string-as-input/44122936#44122936) für die Arbeit mit Zeichenfolgen als Eingabe. – aosmith

Antwort

1

Wenn Sie enquo verwenden, sollten Sie Ihre Funktion ohne Anführungszeichen aufrufen. Zum Beispiel

wizzard_fun_2(sex) 

wird gut funktionieren. Die select Funktion kann Strings oder Symbole annehmen. Das ist beides

select(dt, sex) # more common 
select(dt, "sex") 

arbeiten Aber das ist nicht das gleiche für filter()

filter(sex=="M") 
filter("sex"=="M") 

Also vorsichtig sein, wenn zwischen Streichern und nicht notierten Symbole/Namen zu springen. Wenn Sie Anführungszeichen verwenden, verwenden Sie überhaupt keine Nicht-Standard-Bewertung.

+0

@aosmith Kann jemand mir zeigen, wie man dies tatsächlich tut, indem man ein Character-Argument für die Funktion benutzt, die eine Variable und einen 'Filter' spezifiziert? Keine meiner 'quo',' sym', etc Beschwörungen funktionieren. – joran

+0

@joran: 'f <- Funktion (param1) {par1 <- rlang :: sym (param1); dt%>% select (Höhe, !! (par1))%>% filter ((!! par1) == 'M')}; f ("Sex") sollte den Trick machen. – MrFlick

+0

Ah, yikes, du musst die Parens in '(!! par1) haben' scheint es. Das scheint ... knifflig. – joran

1

In der Funktion verwenden Sie enquo, aber dann, wenn Sie die Funktion aufrufen übergeben Sie den Spaltennamen als Zeichenfolge und nicht den nackten Namen. Sie müssen nur den Namen der bloßen Spalte verwenden, wenn Sie die Funktion aufrufen, und sie funktioniert wie geschrieben.


library(dplyr) 
#> 
#> Attaching package: 'dplyr' 
#> The following objects are masked from 'package:stats': 
#> 
#>  filter, lag 
#> The following objects are masked from 'package:base': 
#> 
#>  intersect, setdiff, setequal, union 

dt <- tibble(
    sex = rep(c("F","M"), 50), 
    height = runif(100, 1, 1000), 
    weight = rep(c(2, 100), 50), 
    value = runif(100, 1, 1000) 
) 


wizzard_fun_2 <- function(param1){ 
    par1 <- enquo(param1) 

    dt %>% select(height, !!par1) %>% 
    filter((!!par1) == "M") 
} 

wizzard_fun_2(sex) 

#> # A tibble: 50 x 2 
#>  height sex 
#>  <dbl> <chr> 
#> 1 871.7788  M 
#> 2 467.9220  M 
#> 3 272.6478  M 
#> 4 445.1101  M 
#> 5 682.2095  M 
#> 6 831.8522  M 
#> 7 727.9525  M 
#> 8 203.7829  M 
#> 9 742.3000  M 
#> 10 322.0473  M 
#> # ... with 40 more rows