geom_text () на фасетных панелях вызывает изменения в отображении символов - PullRequest
1 голос
/ 30 мая 2020

Я строю многогранный сюжет, где каждая панель имеет 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 () переназначает уровни факторов, указанные в "типе", после того, как я явно указал их как для данных графика, так и для структуры данных метки. Это переназначение (на что-то похожее на алфавит) отбрасывает и цвета, и формы.

1 Ответ

0 голосов
/ 01 июня 2020

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

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)

enter image description here

EDIT:

Или, альтернативно, вы можете установить 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)

enter image description here

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

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)

enter image description here

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

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)

Надеюсь, это помогло!

...