2017-11-24 4 views
2

Ich versuche, eine Funktion zu schreiben, die eine vom Benutzer übergebene Variable aus dem resultierenden Datenrahmen ausschließen muss. Ich nutze diese Gelegenheit auch, um etwas mehr über die neue dplyr-Syntax zu erfahren.Verwenden Sie Negation mit Auswählen in dplyr 0.7.x

Die Funktion verhält sich wie eine Kreuzverbindung für Datenrahmen. Ich möchte es als eine saubere Art der Duplizierung von Daten über Parameter einer Funktion verwenden.

Die Funktion arbeitet wie folgt:

crossjoin_df <- function(df1, df2, temp_col = ".k") { 
    df1 <- df1 %>% 
    mutate(!!temp_col := 1) 

    df2 <- df2 %>% 
    mutate(!!temp_col := 1) 

    out <- left_join(df1, df2, by = temp_col) 

    # I'm trying to replace the next line 
    out[,!names(out)==temp_col] 
} 

params <- data.frame(k = c(11,10), 
       n = c(27,26)) 

data <- data.frame(a = 1:3, 
       b = 4:6) 

crossjoin_df(params, data) # 6 row data set 

ich sehen will, ob es möglich ist, die letzte Anweisung mit einer verrohrt select-Anweisung zu ersetzen. Die Negation scheint jedoch nicht zu funktionieren.

Ich kann so etwas wie bekommen:

out %>% select(!!temp_col) 

zu arbeiten, aber das offenbar wählt nur .k. Ich kann nichts erhalten wie:

out %>% select(-!!temp_col) 

zu arbeiten.

+1

Seit 'temp_var' ein strin ist g, müssen Sie 'rlang :: sym' verwenden, um es in eine Ausnahmebedingung umzuwandeln, wenn Sie mit' !! ', z. 'out%>% select (- !! rlang :: sym (temp_col)) ' – alistaire

+0

Danke, mein Verständnis ist, dass ich' temp_var' nicht blank haben kann, weil ich es auf der LHS einer 'muate' Anweisung brauche . Ich bin mir nicht sicher, ob es einen saubereren Weg gibt. Ich hatte gehofft, nur bei dplyr bleiben zu können. – vitallish

Antwort

2

Sie werden rlang benötigen, die Backend-Paket für dplyr, das ordentlich eval ermöglicht, ob Sie weiterhin Zeichenfolgen verwenden möchten, in diesem Fall benötigen Sie sym eine Zeichenfolge in einen quosure zu drehen:

library(dplyr) 

params <- data.frame(k = c(11,10), 
        n = c(27,26)) 

data <- data.frame(a = 1:3, 
        b = 4:6) 

crossjoin_df <- function(df1, df2, temp_col = ".k") { 
    df1 <- df1 %>% mutate(!!temp_col := 1) 

    df2 <- df2 %>% mutate(!!temp_col := 1) 

    left_join(df1, df2, by = temp_col) %>% 
     select(-!!rlang::sym(temp_col)) 
} 

crossjoin_df(params, data) 
#> k n a b 
#> 1 11 27 1 4 
#> 2 11 27 2 5 
#> 3 11 27 3 6 
#> 4 10 26 1 4 
#> 5 10 26 2 5 
#> 6 10 26 3 6 

... oder wechseln Sie zu voll ordentlich eval, in welchem ​​Fall Sie quo_name benötigen einen quosure in einen Namen zu machen:

crossjoin_df <- function(df1, df2, temp_col = .k) { 
    temp_col <- enquo(temp_col) 

    df1 <- df1 %>% mutate(!!rlang::quo_name(temp_col) := 1) 

    df2 <- df2 %>% mutate(!!rlang::quo_name(temp_col) := 1) 

    left_join(df1, df2, by = rlang::quo_name(temp_col)) %>% 
     select(-!!temp_col) 
} 

crossjoin_df(params, data) 
#> k n a b 
#> 1 11 27 1 4 
#> 2 11 27 2 5 
#> 3 11 27 3 6 
#> 4 10 26 1 4 
#> 5 10 26 2 5 
#> 6 10 26 3 6 

Alternativ können Sie nur tidyr::crossing:

tidyr::crossing(params, data) 
#> k n a b 
#> 1 11 27 1 4 
#> 2 11 27 2 5 
#> 3 11 27 3 6 
#> 4 10 26 1 4 
#> 5 10 26 2 5 
#> 6 10 26 3 6 
0

Sie können one_of verwenden und dann die Auswahl negieren mit -:

out %>% select(-one_of(temp_col)) 

crossjoin_df <- function(df1, df2, temp_col = ".k") { 
    # `$`(df1, temp_col) <- 1 
    df1 <- df1 %>% 
    mutate(!!temp_col := 1) 

    # `$`(df2, temp_col) <- 1 
    df2 <- df2 %>% 
    mutate(!!temp_col := 1) 

    left_join(df1, df2, by = temp_col) %>% select(-one_of(temp_col)) 

} 

params <- data.frame(k = c(11,10), 
       n = c(27,26)) 

data <- data.frame(a = 1:3, 
       b = 4:6) 

crossjoin_df(params, data) 

# k n a b 
#1 11 27 1 4 
#2 11 27 2 5 
#3 11 27 3 6 
#4 10 26 1 4 
#5 10 26 2 5 
#6 10 26 3 6 
+0

Das funktioniert definitiv, aber ich bin nicht sicher, dass es im Geiste der neuen Syntax/Konzepte von Quorationen ist. – vitallish

+1

Mein Verständnis ist, dass * resource * vorhanden ist, um die Fähigkeit der Programmierung mit dplyr in einem nicht standardisierten Evaluierungsstil zu verbessern, d. H. Um '* _' Verben abzulehnen. Ich würde also annehmen, dass 'select' mit ausgewählten Hilfsfunktionen immer noch eine der kanonischen Möglichkeiten ist, dies zu tun. Wenn du es vorziehst, * abzubrechen *, sollte der Kommentar von @alistaire der richtige Weg sein. – Psidom

0

Dies sollte auch funktionieren:

out %>% select_(paste0("-",temp_col)) 
+0

Danke, aber ich denke dplyr bewegt sich weg von '* _' Verben – vitallish

+1

Sie werden nicht beibehalten oder vorgebracht, aber sie werden nicht aus dem Paket in mehreren Jahren oder jemals entfernt werden :).Aber ja, wahrscheinlich besser, um @ Psidoms Antwort zu verwenden, ich erwähnte es der Vollständigkeit halber. –

Verwandte Themen