2017-11-30 173 views
6

Próbuję utworzyć kilka pojedynczych działek z tej samej data.frame z innej kolejności poziomów czynnika na osi y dla każdej działki. Każda działka ma na celu stopniowe obniżanie poziomów czynników na y.R: kolejność poziomów czynnikiem dla kilku pojedynczych działek

Wiem, że można to zrobić ręcznie dla każdego poletka, ale szukam bardziej skuteczny i elegancki sposób, ponieważ będę miał sporo działek, które trzeba utworzyć. Nie musi to obejmować użycia facet_wrap, jeśli jest inny sposób, może z pętlami itp.?

library(ggplot2) 
library(dplyr) 
data("diamonds") 

oddaniem zestawu danych i agregowanie przez dwóch poziomach Factor (jasność i cięcia):

means <- diamonds %>% 
group_by(clarity, cut) %>% 
summarise(carat = mean(carat)) 

Tu kolejność przez średnią jednego czynnika, ale ostatecznie chciałbym uporządkować oddzielnie dla każdej powierzchni (zmniejszając średnią klarowność).

means$clarity <- reorder(means$clarity, means$carat, FUN = mean) 

Tworzenie oddzielnych wykresów z face_wrap. Używanie coord_flip do łatwiejszego porównywania wykresów.

ggplot(means, aes(x = clarity, y = carat)) + 
    geom_col() + 
    facet_wrap(~cut, ncol = 1) + 
    coord_flip() 

Zobaczysz, że to tworzy oddzielne wykresy dla każdego typu cięcia ale kolejność poziomów czynnika na osi Y nie są właściwe dla każdego indywidualnego przypadku. Jak mogę je zamówić poprawnie, bez konieczności ręcznego wykonywania każdego rodzaju cięcia?

+2

Oczywiście nie jest to dokładnie to, co chcesz, ale skoro pytasz o eleganckie rozwiązanie, myślę tylko o napisaniu funkcji, która tworzy indywidualne wykresy (używając 'ggplot (znaczy, aes (x = reorder (klarowność, karat), y = karat))', 'lapp ly' przez fasety, a następnie ponownie połączyć pojedyncze działki za pomocą 'gridExtra'. Dodałoby tylko kilka linii do twojego kodu. – yoland

Odpowiedz

6

Można to zrobić w jednej działce wykorzystując dwie funkcje:

reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) { 
    new_x <- paste(x, within, sep = sep) 
    stats::reorder(new_x, by, FUN = fun) 
} 


scale_x_reordered <- function(..., sep = "___") { 
    reg <- paste0(sep, ".+$") 
    ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...) 
} 

dostępny na github dgrtwo/drlib

ggplot(means, aes(x = reorder_within(clarity, carat, cut, mean), y = carat)) + 
    geom_col() + 
    scale_x_reordered() + 
    facet_wrap(~cut, scales = "free_y", ncol = 1) + 
    coord_flip() 

enter image description here