слой ggplot нарушает порядок при размещении первым

#r #ggplot2

#r #ggplot2

Вопрос:

Мой график имеет категориальную ось X и несколько типов элементов для рисования:

   dt1 <- fread('
    ID    type value
    a1     bar   40 
    a1   point   30 
    b1     bar   50 
    b1   point   20 
    c1     bar   30 
    c1   point   50 
    c1   point   20 
    d1   point   30 
    d1   point   50 
    e1    none   50 
    a2     bar   45 
    a2   point   30 
    ')
  
  # I want some custom order on the plot:
  dt1[, ID:=factor(ID, levels=unique(ID[order(value)]))]
  #  here it will be  b1 - c1 - a1 - d1 - a2
  

Если я построю график с geom_point() последующим geom_bar() , порядок X осей будет правильным:

 ggplot(dt1, aes(x=ID,y=value)) 
  geom_point(data=dt1[type=='point',], size=5, col='red')  
  geom_bar(  data=dt1[type=='bar',], stat='identity', alpha=0.5)
  

правильный порядок

Но если у меня есть geom_bar() в качестве первого слоя, за которым следует geom_point() , он игнорирует уровни моей x ID переменной () и переупорядочивает ее в алфавитном порядке:

 ggplot(dt1, aes(x=ID,y=value)) 
  geom_bar(  data=dt1[type=='bar',], stat='identity', alpha=0.5) 
  geom_point(data=dt1[type=='point',], size=5, col='red')
  

неправильный порядок столбцов

(Обратите внимание, что geom_bar() , поскольку один слой имеет правильный порядок, проблема возникает только тогда, когда за ним следует другой уровень!) Почему это происходит и как это исправить? Я нашел один обходной путь с добавлением scale_x_discrete(drop=FALSE) , но мне это не нравится, потому что он добавляет категории, которых там не должно быть:

 ggplot(dt1, aes(x=ID,y=value)) 
  geom_bar(  data=dt1[type=='bar',], stat='identity', alpha=0.5) 
  geom_point(data=dt1[type=='point',], size=5, col='red') 
  scale_x_discrete(drop=F)
  

см. Добавленный quot;e1quot;

Ответ №1:

Это происходит потому, что более поздний слой содержит уровни, отсутствующие в более раннем слое (напомним, что неиспользуемые уровни по умолчанию удаляются, поэтому после построения слоя все неиспользуемые уровни удаляются). ggplot() не знает, как объединить (что становится) два разных фактора, чтобы они были преобразованы в вектор символов (а затем обратно в фактор) перед нанесением на график. Вы можете использовать limits аргумент in scale_x_discrete() , чтобы указать желаемый порядок.

 library(ggplot2)
library(data.table)

ggplot()   
  aes(x=ID,y=value)  
  geom_col(data=dt1[type=='bar',], alpha=0.5)  
  geom_point(data=dt1[type=='point',], size=5, col='red')  
  scale_x_discrete(limits = levels(droplevels(dt1$ID[dt1$type %in% c("bar", "point")])))
  

Вы можете сделать это немного более аккуратно, установив свои данные перед построением графика:

 dt2 <- dt1[type != "none"]
dt2[, ID:=factor(ID, levels=unique(ID[order(value)]))]

ggplot()  
  aes(x=ID,y=value)  
  geom_col(data=dt1[type=='bar',], alpha=0.5)  
  geom_point(data=dt1[type=='point',], size=5, col='red')  
  scale_x_discrete(limits = levels(dt2$ID))
  

Комментарии:

1. Спасибо! Как вы думаете, может ли быть какой-либо способ достичь этого без явного перечисления %in% c("bar", "point") ? В моем реальном случае у меня много критериев, поэтому я бы предпочел не перечислять их снова вручную.

2. Я обновил — я бы подмножил данные перед построением графика.

3. понял, спасибо! (У меня есть своего рода продолжение этого вопроса, но я решил опубликовать его отдельно)