2017-04-14 62 views
8
library(dplyr) #Devel version, soon-to-be-released 0.6.0 
library(tidyr) 
library(ggplot2) 
library(forcats) #for gss_cat data 

我試圖寫一個從即將要發佈的dplyr devel的版本tidyr組合在一起quosures功能使用開發人員版本dplyr的enquo和quo_name的一個功能:: gather和ggplot2。到目前爲止,它似乎與tidyr一起工作,但我在繪圖時遇到了麻煩。如何使用tidyr和GGPLOT2

下面的功能似乎與tidyr的收集工作:

GatherFun<-function(gath){ 
gath<-enquo(gath) 

gss_cat%>%select(relig,marital,race,partyid)%>% 
gather(key,value,-!!gath)%>% 
count(!!gath,key,value)%>% 
mutate(perc=n/sum(n)) 
} 

但我不能想出如何使該地塊的工作。我嘗試用ggplot2使用!! gath,但它不起作用。

GatherFun<-function(gath){ 
gath<-enquo(gath) 

gss_cat%>%select(relig,marital,race,partyid)%>% 
gather(key,value,-!!gath)%>% 
count(!!gath,key,value)%>% 
mutate(perc=n/sum(n))%>% 
ggplot(aes(x=value,y=perc,fill=!!gath)+ 
geom_col()+(facet_wrap(~key, scales = "free") + 
    geom_text(aes(x = "value", y = "perc", 
         label = "perc", group = !!gath), 
       position = position_stack(vjust = .05)) 
} 
+0

我要回答的更近的問題適用於:使用dplyr SE與GGPLOT2(https://stackoverflow.com/questions/45279287/use-dplyr-se-with-ggplot2/47044567#47044567)。簡而言之,我建議你使用aes_(x =〜value,y =〜perc,fill = gath)。當你已經有quards在使用時,語法比使用aes_string更清晰。 – Stanwood

回答

6

我覺得主要的問題是ggplot是貪婪的時候,它會評估!!gath和做!(!gath),拋出一個錯誤not(gath)已經沒有意義。當我嘗試使用!!時,我遇到了這個問題,所以我對使用它的糖形式感到厭倦。

如果有人更精確地可以正確識別問題,它肯定會有幫助。

gather_func = function(gath) { 

    gath = enquo(gath) 

    gss_cat %>% 
    select(relig, marital, race, partyid) %>% 
    gather(key, value, -!!gath) %>% 
    count(!!gath, key, value) %>% 
    mutate(perc = round(n/sum(n), 2)) %>% 
    ggplot(aes(x = value, y = perc, fill = eval(rlang::`!!`(gath)))) + 
    geom_col() + 
    facet_wrap(~key, scales = "free") + 
    geom_text(
     aes(
     x = value, 
     y = perc, 
     label = perc, 
     group = eval(rlang::`!!`(gath)) 
    ), 
     position = position_stack(vjust = .05) 
    ) 
} 

您在問題中編寫的函數調用似乎存在一些錯誤。適當的間隔你的代碼將有助於避免這一點

你也沒有使用rlang電話,我只是沒有安裝最新的dplyr版本。

編輯使用更簡單mtcars例如一些想法:

TBH我不是很確定什麼是怎麼回事,但我想這是與事實ggplot2現在是比較老的做,有一個稍微不同的設計?走進aesdebug,我們發現類似的結構,以

structure(list(x = mpg, y = eval(rlang::UQE(var))), .Names = c("x", 
"y"), class = "uneval") 

(這將不通過翻譯運行,但大致的結構是什麼樣子)。我認爲這說明了爲什麼eval電話是必要的,o/w ggplot試圖將rlang::UQE(var)映射到y審美,並報告它不知道如何處理類name的東西。 eval評估名稱,例如cyl,那麼審美可以被映射爲正常。

我想dplyr動詞沒有這個額外的映射步驟,其中的參數被以相同的方式操縱到一些中間結構中,所以我們沒有這個問題。

此外,當我說你不必使用rlang調用,這是因爲我認爲這個功能被重新導出到新的dplyr版本。由於前面提到的整個!!(...)!(!(...)),我更喜歡使用rlang::"!!"rlang::UQE(我相信這完全等價)。

大部分是猜測,如果有人能糾正我的任何錯誤,我將不勝感激。

+0

謝謝你的答案。所以當你說我不需要使用rlang調用時,我仍然使用 - fill = eval('!!'(gath))))?你能詳細闡述一下嗎?另外,「eval」是做什麼的?我對SE和NSE仍然很陌生,所以任何額外的細節將不勝感激! – Mike

+0

添加了一個編輯,讓我們猜測爲什麼NSE在此處無法正常工作。上面的一些東西似乎違反了NSE小插曲中概述的慣例:http://dplyr.tidyverse.org/articles/programming.html,因此我覺得'ggplot'可能略微超出了本文的範圍,到它的年齡 –

8

爲了使這項工作,我不得不使用dplyr::quo_name改變平靜成一個字符串。我還必須使用ggplot2::aes_string,這也需要所有的輸入爲字符串,因此引用""

GatherFun <- function(gath){ 
    gath <- enquo(gath) 
    gathN <- quo_name(gath) 

    gss_cat %>% 
    select(relig, marital, race, partyid) %>% 
    gather(key, value, -!!gath) %>% 
    count(!!gath, key, value) %>% 
    mutate(perc = round(n/sum(n), 2)) %>% 
    ggplot() + 
    geom_col(aes_string(x = "value", y = "perc", fill = gathN)) + 
    facet_wrap(~key, scales = "free") + 
    geom_text(aes_string(x = "value", y = "perc", label = "perc", group = gathN), 
       position = position_stack(vjust = .05)) 
} 
+1

有什麼辦法可以避免使用ggplot2 :: aes_string? – Mike

+1

我認爲這是比接受的答案更好的解決方案 – Andrie

+0

@Andrie我同意。我發佈後,OP的評論如何做到這一點W/o aes_string –

0

我最近在別處回答了這個問題(Use dplyr SE with ggplot2)。不知道如何標記重複,所以我會在這裏重複。

如果您已經辦理quosures語法是清潔,如果你使用 aes_,而不是aes_string

這段代碼應該在你的例子中工作。請注意,所有硬編碼變量(value,perc,key)都是在用戶直接使用靜態(gath)時用tilda引用的。

ggplot(aes_(x = ~value, y = ~perc, fill = gath) + 
    geom_col() + 
    facet_wrap(~key, scales = "free") + 
    geom_text(aes_(x = ~value, y = ~perc, label = ~perc, group = gath), 
      position = position_stack(vjust = .05))