Текст на оси цвета на основе значения переменной на фасетной диаграмме - PullRequest
1 голос
/ 16 июня 2020

У меня есть два фасетных графика, и я хочу, чтобы текст оси был серым, когда заданная переменная принимает значение NA или 0. В настоящее время это работает для одного графика, но когда я их фасонирую, цвет текста не совпадает с значения бара. См. Изображение ниже:

# create df
text <-   
"   country          domain var_name    perc           color
        A             'domain c           Val2      NA            grey
        A             'domain c'           Val1      NA            grey
        A             'domain c'           Val3 0.01670          orange
        A             'domain c'           Val8 0.00000            grey
        A             'domain c'           Val9      NA            grey
        A             'domain c'          Val11 0.02510          orange
        A             'domain c'          Val19 0.01890          orange
        A           'domain d'          Val16 0.04840          purple
        A            'domain a'           Val5 0.00776 darkolivegreen4
       A            'domain a'           Val6 0.02390 darkolivegreen4
       A            'domain a'           Val7 0.00247 darkolivegreen4
       A            'domain a'          Val10 0.03840 darkolivegreen4
       A            'domain a'          Val13 0.02490 darkolivegreen4
       A            'domain a'          Val18      NA            grey
       A            'domain b'           Val4 0.01630            navy
       A             'domain b'          Val14 0.01610            navy
       A             'domain b'          Val12 0.05180            navy
       A             'domain b'          Val17 0.01770            navy
       A             'domain b'          Val15 0.03550            navy
       B             'domain c'           Val2 0.01440          orange
       B             'domain c'           Val1      NA            grey
       B             'domain c'           Val3 0.02590          orange
       B             'domain c'           Val8 0.00000            grey
       B             'domain c'           Val9     NaN            grey
       B             'domain c'          Val11 0.02900          orange
       B             'domain c'          Val19 0.00000            grey
       B 'domain d'          Val16 0.00261          purple
       B            'domain a'           Val5 0.10900 darkolivegreen4
       B            'domain a'           Val6 0.00702 darkolivegreen4
       B            'domain a'           Val7 0.01330 darkolivegreen4
       B            'domain a'          Val10 0.00861 darkolivegreen4
       B            'domain a'          Val13 0.06050 darkolivegreen4
       B            'domain a'          Val18 0.07770 darkolivegreen4
       B            'domain b'           Val4 0.00797            navy
       B             'domain b'          Val14 0.05230            navy
       B             'domain b'          Val12 0.04290            navy
       B             'domain b'          Val17 0.03190            navy
       B             'domain b'          Val15 0.06940            navy" 

tbl <- read.table(text = text, header = T, fill = T) 

# overwrite coord_polar function
cp <- coord_polar(theta = "x")
cp$is_free <- function() TRUE

# plot
p <-
  ggplot(tbl, aes(x = forcats::as_factor(var_name), y = perc)) +
  cp +
  geom_bar(stat = "identity", aes(fill = color)) +
  scale_y_continuous(labels = scales::label_percent()) + 
  scale_fill_identity(name = "Domain") +
  facet_grid(. ~ country, scales = "fixed") +
  theme_bw() +
  theme(aspect.ratio = 1,
        strip.text = element_text(size = 16),
        axis.title = element_text(size = 18),
        title = element_text(size = 20),
        axis.text.x = element_text(colour = tbl$color, face = "bold"),
        legend.text = element_text(size = 14))

p

Что дает это изображение:

this image

Обратите внимание, как для страны B Var18 серый, когда явно есть ненулевое количество этой var. Это потому, что в стране А это значение равно 0.

Я бы не хотел использовать Grid ::, но мы будем очень благодарны за любые советы о том, как решить эту проблему!

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Чуть быстрее следует совету З.Лина и использовать geom_text. Это быстрый обходной путь, и он не идеален, потому что текст не заканчивается на самом краю, и по какой-то причине я не могу заставить clip = off работать в corre_polar.

(я несколько изменил данные, потому что их было трудно читать)

library(ggplot2)

maxval <- max(tbl$perc, na.rm = T)

ggplot(tbl, aes(x = var_name, y = perc)) +
  coord_polar(theta = "x") +
  geom_col(aes(fill = color)) +
  geom_text(aes(x = var_name, y = maxval + 0.02, color = color, label = var_name),
              size = 10*5/14) +
  scale_fill_identity(name = "Domain") +
  scale_color_identity(name = "Domain") +
  facet_grid(. ~ country, scales = "fixed") +
  theme_minimal(base_size = 10) +
  theme(axis.text.x = element_blank())

#> Warning: Removed 6 rows containing missing values (position_stack).

data

text <-   
  "country          domain var_name    perc           color
        A             domainc           Val2      NA            grey
        A             domainc           Val1      NA            grey
        A             domainc           Val3 0.01670          orange
        A             domainc           Val8 0.00000            grey
        A             domainc           Val9      NA            grey
        A             domainc          Val11 0.02510          orange
        A             domainc          Val19 0.01890          orange
        A           domaind          Val16 0.04840          purple
        A            domaina           Val5 0.00776 darkolivegreen4
       A            domaina           Val6 0.02390 darkolivegreen4
       A            domaina           Val7 0.00247 darkolivegreen4
       A            domaina          Val10 0.03840 darkolivegreen4
       A            domaina          Val13 0.02490 darkolivegreen4
       A            domaina          Val18      NA            grey
       A            domainb           Val4 0.01630            navy
       A             domainb          Val14 0.01610            navy
       A             domainb          Val12 0.05180            navy
       A             domainb          Val17 0.01770            navy
       A             domainb          Val15 0.03550            navy
       B             domainc           Val2 0.01440          orange
       B             domainc           Val1      NA            grey
       B             domainc           Val3 0.02590          orange
       B             domainc           Val8 0.00000            grey
       B             domainc           Val9     NaN            grey
       B             domainc          Val11 0.02900          orange
       B             domainc          Val19 0.00000            grey
       B            domaind          Val16 0.00261          purple
       B            domaina           Val5 0.10900 darkolivegreen4
       B            domaina           Val6 0.00702 darkolivegreen4
       B            domaina           Val7 0.01330 darkolivegreen4
       B            domaina          Val10 0.00861 darkolivegreen4
       B            domaina          Val13 0.06050 darkolivegreen4
       B            domaina          Val18 0.07770 darkolivegreen4
       B            domainb           Val4 0.00797            navy
       B             domainb          Val14 0.05230            navy
       B             domainb          Val12 0.04290            navy
       B             domainb          Val17 0.03190            navy
       B             domainb          Val15 0.06940            navy" 

tbl <- data.table::fread(text = text, header = T, fill = T) 
1 голос
/ 19 июня 2020

Итак, я нашел способ исправить цвета осей и масштабировать графики с помощью сетки. Основываясь на приведенном выше представлении:

# Generate a function to get the legend of one of the ggplots
get_legend<-function(myggplot){
    tmp <- ggplot_gtable(ggplot_build(myggplot))
    leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
    legend <- tmp$grobs[[leg]]
    return(legend)
  }

# From the full dataset, find the value of the country with the highest percent of any var_name

max <- round(max(tbl$perc), digits = 2)

# create a sequence of length 6 from 0 to the largest perc value
max_seq <- seq(0, max, length = 6)

# initiate empty list 
my_list <- list()

# list of countries to loop through
my_sub <- c("A", "B")

Теперь мы l oop по каждой стране, сохраняя каждый график страны в пустой список.

for(i in my_sub){

  ### Wrangle
  tbl_sub <-
      tbl %>%
      dplyr::mutate(country = as.factor(country),
                    domain = as.factor(domain)) %>%       
      dplyr::filter(country == i),
      dplyr::mutate(perc = ifelse(is.na(perc), 0, perc))

  # Create custom coord_polar arguments 
  cp <- coord_polar(theta = "x", clip = "off")
  cp$is_free <- function() TRUE

  p <-
    ggplot(dplyr::filter(tbl_sub, country == i), 
           aes(x = forcats::as_factor(var_name), 
               y = perc)) +
           cp +
           geom_bar(stat = "identity", aes(fill = color)) +
           facet_grid(. ~ country, scales = "fixed") +
           scale_y_continuous(breaks = c(max_seq), 
                              labels = scales::label_percent(), 
                              limits = c(0, max(max_seq))) +
           scale_fill_identity(guide = "legend", 
                               name = "Domain", 
                               labels = c(darkolivegreen4 = "domain a", 
                                          orange = "domain c", 
                                          navy = "domain b" , 
                                          purple = "domain d", 
                                          grey = "not applicable")) +
           labs(x = "",
                y = "") +
           theme_bw() +
           theme(aspect.ratio = 1,
                 panel.border = element_blank(),
                 strip.text = element_text(size = 16),
                 axis.title = element_text(size = 18),
                 title = element_text(size = 20),
                 axis.text.x = element_text(colour = tbl_new$color, face = "bold"),
                 legend.text = element_text(size = 14))

  my_list[[i]] <- p

  }

Теперь у нас есть графики в list, мы хотим поиграть с легендой и использовать grid :: и gridExtra, чтобы построить все вместе.

# pull legend from first ggplot in the list 
legend <- get_legend(my_list[[1]])

# remove legends from all the plots in the list
for(i in 1:length(my_list)){
  my_list[[i]] <- my_list[[i]] + theme(legend.position = "none")
}

# plot everything together
p <- grid.arrange(arrangeGrob(
  grobs = my_list,
  nrow = round(length(my_sub)/2, 0),
  left = textGrob("Y axis",
                    gp = gpar(fontsize = 20),
                    rot = 90),
  bottom = textGrob("X axis",
                      gp = gpar(fontsize = 20),
                      vjust = -3),
  top = textGrob("Big plot",
                   gp = gpar(fontsize = 28, vjust = 2))),
  legend = legend,
  widths = c(9,1,1),
  clip = F)

Это дает следующее изображение: enter image description here

Графики масштабируются по стране с наибольшим значением на c (0 - 11%), и каждая страна имеет уникальные серые значения в зависимости от того, есть ли в столбце c значение 0 или NA.

Я уверен, что есть более простые c решения, но пока это помогает мне!

...