geom_text() на граненых панелях вызывает изменения в отображении символов

Я строю граненый сюжет, где каждая панель имеет 3 разных набора точек, каждая из которых имеет разную форму. Все работает нормально, пока я не пытаюсь добавить текст на каждую панель с помощью geom_text(). Когда я включаю geom_text() в график, я получаю сообщение об ошибке, что у меня «недостаточно значений в ручной шкале: необходимо 4, но предоставлено только 3». Я могу исправить эту проблему, добавив дополнительные формы и цвета, но я не могу контролировать переназначение факторов формы/цвета, которое происходит, когда я добавляю функцию geom_text().

Вот сценарий, который я запускаю:

library(ggplot2)
library(RColorBrewer)
library(cowplot)

make_hist_df <- function (vals, breaks, expt, type) {
  hist_d <- hist(vals,breaks=breaks,plot=FALSE)
  hist_d_nz<-hist_d$counts > 0
  n_d_nz<-length(hist_d$counts[hist_d_nz])
  hist_df <- data.frame(expt=character(n_d_nz), counts=numeric(n_d_nz), mids=numeric(n_d_nz),type=character(n_d_nz))
  hist_df$counts <- hist_d$counts[hist_d_nz]
  hist_df$mids <- hist_d$mids[hist_d_nz]
  hist_df$expt = expt
  hist_df$type = type

  return(hist_df)
  }

## get some normal distributions
n1<-rnorm(n=10000, mean=5,sd=1)
n2<-rnorm(n=5000,mean=15,sd=1)
n3<-rnorm(n=2000,mean=25,sd=1)

breaks=seq(0,30,0.5)

tot_hist_df = rbind(
  make_hist_df(n1,breaks,expt='one',type='low'),
  make_hist_df(n2,breaks,expt='one',type='mid'),
  make_hist_df(n3,breaks,expt='one',type='high')
  )

tot_hist_df = rbind(tot_hist_df,
  make_hist_df(n1,breaks,expt='two',type='low'),
  make_hist_df(n2,breaks,expt='two',type='mid'),
  make_hist_df(n3,breaks,expt='two',type='high')
  )

tot_hist_df$expt<-factor(tot_hist_df$expt,levels=c('one','two'), ordered=TRUE)
tot_hist_df$type<-factor(tot_hist_df$type,levels=c('low','mid','high'), ordered=TRUE)

s.open_circ<-1
s.closed_circ<-16
s.triangle <- 2
s.plus<-4
s.dot <- 20
sb.shapes   = c(s.open_circ, s.triangle, s.closed_circ)
sb.shapes_l = c(s.open_circ, s.triangle, s.closed_circ, s.dot)

q_set <- c('N1','N2','N3')
n_q <- length(q_set)

sb.colors <-brewer.pal(max(3,n_q),'Dark2') # 'Dark2', 'Set2', 'Paired'
sb.colors_l <- c(sb.colors,'black')

sb.sizes = rep(1.25,n_q)

## plot out without labels
p1 <- ggplot(data=tot_hist_df,aes(x=mids, y=counts, shape=type, color=type))+geom_point() +
  scale_color_manual(values=sb.colors) +
  scale_shape_manual(values=sb.shapes) +
  facet_wrap(~expt, ncol=2)

## make a label dataframe
hist_label=data.frame(expt=c('one','two'), lab=c('mean 5, 20','mean 5, 20 - dup'),type=c('xlab','xlab'))
hist_label$expt <- factor(hist_label$expt,levels=c('one','two'),ordered=TRUE)
hist_label$type <- factor(hist_label$type,levels=c('low','mid','high','xlab'),ordered=TRUE)

## plot out without labels
p2 <- ggplot(data=tot_hist_df,aes(x=mids, y=counts, shape=type, color=type))+geom_point() +
  geom_text(data=hist_label, aes(x=10,y=1000,label=lab)) +
  scale_color_manual(values=sb.colors_l) +
  scale_shape_manual(values=sb.shapes_l) +
  facet_wrap(~expt, ncol=2)

plot_grid(p1,p2,ncol=1)

И вот что он выдает: плохой сюжет

И цвета, и формы различаются между верхней и нижней панелью.

Я не понимаю, почему geom_text() переназначает уровни факторов, указанные в «типе», после того, как я явно указал их как для графических данных, так и для структуры данных метки. Это переназначение (во что-то похожее на алфавит) отбрасывает как цвета, так и формы.


person Bill Pearson    schedule 30.05.2020    source источник
comment
Нам будет легче помочь вам, если вы предоставите дополнительную информацию. В частности, было бы полезно, если бы вы могли опубликовать (1) графики, чтобы люди могли судить, понимают ли они проблему. (2) Минимальный код построения графика, который создает график с проблемами, а не только с одним слоем. (3) Фрагмент данных, который в сочетании с (2) воспроизведет проблемы, показанные в (1). Фрагменты данных легче всего передаются путем копирования вывода dput(your_data_snippet).   -  person teunbrand    schedule 30.05.2020
comment
Я обновил вопрос функциональным примером и графиком вывода.   -  person Bill Pearson    schedule 01.06.2020


Ответы (1)


Спасибо за воспроизводимый пример. Теперь стало намного яснее понимать, что происходит.

Описываемое вами поведение переназначения связано с тем, что при изучении дискретных значений (обучении шкалы) оно не обновляет метки, полученные из данных гистограммы, с помощью меток, полученных из текстовых данных. Чтобы исправить этот бит, вы можете вручную установить пределы шкалы.

ggplot(data=tot_hist_df,
       aes(x=mids, y=counts, shape=type, color=type))+
  geom_point() +
  geom_text(data=hist_label, 
            aes(x=10,y=1000,label=lab)) +
  scale_color_manual(values=sb.colors_l, limits = levels(hist_label$type)) +
  scale_shape_manual(values=sb.shapes_l, limits = levels(hist_label$type)) +
  facet_wrap(~expt, ncol=2)

введите здесь описание изображения

РЕДАКТИРОВАТЬ:

Или же вы можете установить drop = FALSE в ручных весах:

ggplot(data=tot_hist_df,
       aes(x=mids, y=counts, shape=type, color=type))+
  geom_point() +
  geom_text(data=hist_label, 
            aes(x=10,y=1000,label=lab)) +
  scale_color_manual(values=sb.colors_l, drop = FALSE) +
  scale_shape_manual(values=sb.shapes_l, drop = FALSE) +
  facet_wrap(~expt, ncol=2)

КОНЕЦ РЕДАКТИРОВАТЬ

Ниже приведены несколько советов, которые могут оказаться полезными. Во-первых, вы можете использовать именованные векторы в ручных дискретных шкалах, которые сохранят связь между символом и цветом/формой независимо от того, присутствует ли символ в данных.

Это также полезно, когда вам нужно создать несколько одинаковых графиков, и вы не знаете, присутствует ли только подмножество категорий на каком-либо одном графике.

Обратите внимание, что на приведенном ниже графике цвета правильно сопоставлены с данными, и для неиспользуемого сопоставления символа/цвета not_in_data не отображается элемент легенды.

my_colours <- setNames(object = c(brewer.pal(3, 'Dark2'), 'black', 'blue'), 
                       nm = c(levels(hist_label$type), "not_in_data"))
my_shapes <- setNames(object = c(1, 2, 16, NA), 
                      nm = levels(hist_label$type))

ggplot(data=tot_hist_df,
       aes(x=mids, y=counts, shape=type, color=type))+
  geom_point() +
  geom_text(data=hist_label, 
            aes(x=10,y=1000,label=lab)) +
  scale_color_manual(values=my_colours) +
  scale_shape_manual(values=my_shapes) +
  facet_wrap(~expt, ncol=2)

введите здесь описание изображения

Второй совет заключается в том, что вы можете избежать необходимости включать текст в легенду, если текстовый слой не наследует эстетику основного сюжета (который присваивает форму и цвет текстовому слою, что, вероятно, ему не нужно). Также обратите внимание, что, поскольку шкалу не нужно обновлять для цвета и формы текста, восстанавливается правильный порядок уровней факторов из гистограммы.

ggplot(data=tot_hist_df,
       aes(x=mids, y=counts, shape=type, color=type)) + 
  geom_point() +
  geom_text(data=hist_label, 
            aes(x=10,y=1000, label=lab),
            inherit.aes = FALSE) +
  scale_color_manual(values=my_colours) +
  scale_shape_manual(values=my_shapes) +
  facet_wrap(~expt, ncol=2)

введите здесь описание изображения

Альтернативный способ добиться того же — определить не эстетику в вызове основного сюжета, а вместо этого вызвать ее в точечном слое (график идентичен приведенному выше).

ggplot(data=tot_hist_df) + 
  geom_point(aes(x=mids, y=counts, shape=type, color=type)) +
  geom_text(data=hist_label, 
            aes(x=10,y=1000, label = lab)) +
  scale_color_manual(values=sb.colors) +
  scale_shape_manual(values=sb.shapes) +
  facet_wrap(~expt, ncol=2)

Я надеюсь, что это помогло!

person teunbrand    schedule 31.05.2020
comment
Большое спасибо. Ваше руководство очень ценится. Мне нужно многое узнать о сопоставлении формы/цвета/размера ggplot(). Я боюсь, что экспериментирование может быть очень медленным. Я с нетерпением жду возможности воспользоваться вашим советом. - person Bill Pearson; 01.06.2020