2017-08-01 8 views
8

Ich bin verwirrt darüber, wie Funktionsargumente in dplyr- und ggplot-Codes übergeben werden. Ich verwende die neueste Version von dplyr und ggplot2 Hier ist mein Code einen BarPlot (Klarheit vs mittlerem Preis)übergeben Sie Funktionsargumente sowohl an dplyr als auch an ggplot

diamond.plot<- function (data, group, metric) { 
    group<- quo(group) 
    metric<- quo(metric) 
    data() %>% group_by(!! group) %>% 
      summarise(price=mean(!! metric)) %>% 
      ggplot(aes(x=!! group,y=price))+ 
      geom_bar(stat='identity') 
} 

diamond.plot(diamonds, group='clarity', metric='price') 

Fehler zu erzeugen:

Error in UseMethod("group_by_") : no applicable method for 'group_by_' applied to an object of class "packageIQR" 

Für die neueste Version von dplyr, Die unterstrichenen Verben_() sind leise veraltet. Es scheint so, als ob wir Quorungen verwenden sollten.

meine Fragen:

  • Kann jemand die aktuelle Best Practice für das klären?
  • Was war mit dem obigen Code falsch? (kein Unterstrich dplyr Verben ..)

  • In ggplot, ich weiß, wir können aes_string() verwenden, aber in meinem Fall wird nur einer der Parameter in der AES von Funktionsargument übergeben.

Vielen Dank im Voraus.

Antwort

6

Ich glaube nicht, dass Sie den "richtigen" Weg noch nicht können, da ggplot2 die Tidyeval-Syntax nicht unterstützt, aber es kommt.

Die beste Praxis mit dem dplyr Teil des Codes wäre:

library(tidyverse) 
library(rlang) 

diamond_data <- function (data, group, metric) { 
    quo_group <- enquo(group) 
    quo_metric <- enquo(metric) 
    data %>% 
    group_by(!!quo_group) %>% 
    summarise(price=mean(!!quo_metric)) 
} 
diamond_data(diamonds, clarity, price) 

um den Mangel an Unterstützung der tidyeval in ggplot2 arbeiten zu können, könnte die Anführungszeichen um die Variablen in der Funktion tun (beachten Anruf):

diamond_plot <- function (data, group, metric) { 
    quo_group <- parse_quosure(group) 
    quo_metric <- parse_quosure(metric) 
    data %>% 
     group_by(!!quo_group) %>% 
     summarise(price=mean(!!quo_metric)) %>% 
     ggplot(aes_(x = as.name(group), y=as.name(metric)))+ 
     geom_bar(stat='identity') 
} 
diamond_plot(diamonds, "clarity", "price") 

EDIT - @ Lionels Kommentar Folgende:

diamond_plot <- function (data, group, metric) { 
    quo_group <- sym(group) 
    quo_metric <- sym(metric) 
    data %>% 
     group_by(!!quo_group) %>% 
     summarise(price=mean(!!quo_metric)) %>% 
     ggplot(aes_(x = quo_group, y= quo_metric)) + 
     geom_bar(stat='identity') 
} 
diamond_plot(diamonds, "clarity", "price") 
+0

Danke – zesla

+0

@sinQueso würde ich nur verwenden 'sym()' (oder 'as.name()') statt 'parse_quosure()' in diesem Fall. – lionel

+0

danke für den Vorschlag @lionel, habe ich meine Antwort aktualisiert – sinQueso

3

Die Antwort von sinQueso ist vielversprechend, aber sie vermisst den Zweck einer Funktion, die an verschiedene Datenrahmen angepasst werden kann. Der „Preis“ Variable wird in der Funktion in der folgenden Zeile codiert:

summarise(price=mean(!!quo_metric)) %>% 

so wird diese Funktion nur, wenn die Eingangsgröße „Preis“.

Hier ist eine bessere Lösung, die für jeden Datenrahmen verwendet werden kann:

diamond_plot <- function (data, group, metric) { 
     quo_group <- sym(group) 
     quo_metric <- sym(metric) 
     summary <- data %>% 
       group_by(!!quo_group) %>% 
       summarise(mean=mean(!!quo_metric)) 
       ggplot(summary, aes_string(x = group, y= "mean")) + 
       geom_bar(stat='identity') 
} 
diamond_plot(diamonds, "clarity", "price") 
3

Sie können sogar noch weiter als Daniels Lösung gehen, so dass der Name der Zusammenfassung Variable (metrisch) mit dem Eingang ändert.

diamond_plot <- function(data, group, metric) { 
    quo_group <- rlang::sym(group) 
    quo_metric <- rlang::sym(metric) 
    metric_name <- rlang::sym(stringr::str_c("mean_", metric)) 
    data %>% 
     group_by(!!quo_group) %>% 
     summarize(!!metric_name := mean(!!quo_metric)) %>% 
     ggplot(aes_(x = quo_group, y = metric_name)) + 
     geom_bar(stat = 'identity') 
} 
diamond_plot(diamonds, "clarity", "price") 
0

Die „tidyeval“ Art und Weise für dieses Problem zu mir sieht aus, als Kombination von quo_name und aes_string Funktionen. Vermeiden Sie die Verwendung von nachgestellten Unterstrich-Verben wie aes_, da sie veraltet sind.

diamond_plot <- function(data, group, metric) { 
    quo_group <- enquo(group) 
    str_group <- quo_name(quo_group) 

    quo_metric <- enquo(metric) 

    summary <- data %>% 
    groupby(!!quo_group) %>% 
    summarise(mean = mean(!!quo_metric)) 

    ggplot(summary) + 
    geom_bar(aes_string(x = str_group, y = "mean"), stat = "identity") 
} 

diamond_plot(diamnonds, clarity, price) 
Verwandte Themen