Как установить ограничения по оси Y с закругленными гранями?

У меня есть этот график, и мне нужно округлить ось у, так что то, что кажется приемлемым, за исключением того факта, что я хотел бы не просто показывать 1 значение на оси у. Я хотел бы добавить "limit" в функцию "scale_y_continuous", чтобы предельные значения для каждого графика фасета были уникальными для отдельного фасета.

вот график, показывающий только 60 и 80 по оси Y

dat = data.frame(x = c(1,2,3,1,2,3),A=c(80.6, 82,83,60,61,62),A_up =c(81,84,85,62,63,64), A_low =c(79,78,81,59,58,57), group = c("z","z","z","y","y","y"))
ggplot(data=dat , aes(x=as.factor(x), y=A, group = 1)) + #, color =Group, group = Group 
  geom_line()  + geom_point() + # facet_wrap(~COUNTERPARTY_STRATEGY ,ncol=2)
  geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
     scale_y_continuous(breaks = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                      labels = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 )
                      ) +
    facet_wrap(~group ,ncol=2, scales = "free_y") 

Теперь я добавляю предел в шкале y непрерывно, и он применяет предел в глобальном масштабе.

dat = data.frame(x = c(1,2,3,1,2,3),A=c(80.6, 82,83,60,61,62),A_up =c(81,84,85,62,63,64), A_low =c(79,78,81,59,58,57), group = c("z","z","z","y","y","y"))
ggplot(data=dat , aes(x=as.factor(x), y=A, group = 1)) + #, color =Group, group = Group 
  geom_line()  + geom_point() + # facet_wrap(~COUNTERPARTY_STRATEGY ,ncol=2)
  geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
     scale_y_continuous(breaks = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                      labels = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                     # limits =  c( floor(  min(dat$A_low[dat$group =="z"])  /10)*10 ,ceiling(max(dat$A_up[dat$group =="z"])/10)*10 )   
                      #limits =  c( floor(  min(dat$A_low[dat$group =="z"])  /10)*10 ,ceiling(max(dat$A_up[dat$group =="z"])/10)*10 ) 
                      limits =  c( floor(  min(dat$A_low)  /10)*10 ,ceiling(max(dat$A_up)/10)*10 ) 
                      ) +
    facet_wrap(~group ,ncol=2, scales = "free_y") 

т.е.

c( floor( min(dat$A_low) /10)*10 ,ceiling(max(dat$A_up)/10)*10 )

50 и 90

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

поэтому правильный участок будет иметь пределы

c( floor( min(dat$A_low[dat$group =="y"]) /10)*10 ,ceiling(max(dat$A_up[dat$group =="y"])/10)*10 )

50 и 70

и левый участок будет иметь предел

c( floor( min(dat$A_low[dat$group =="z"]) /10)*10 ,ceiling(max(dat$A_up[dat$group =="z"])/10)*10 )

70 и 90

Как можно отрегулировать пределы, чтобы они были специфичны для отдельных графиков?

3 ответа

dat = data.frame(x = c(1,2,3,1,2,3),A=c(80.6, 82,83,60,61,62),A_up =c(81,84,85,62,63,64), A_low =c(79,78,81,59,58,57), group = c("z","z","z","y","y","y"))


dat <- data.table(dat)

dat[, y_min := floor(  min(A_low)  /10)*10, by = group]
dat[, y_max := ceiling(max(A_up)/10)*10 , by = group]

ggplot(data=dat , aes(x=as.factor(x), y=A, group = 1)) + #, color =Group, group = Group 
  geom_line()  + geom_point() + # facet_wrap(~COUNTERPARTY_STRATEGY ,ncol=2)
  geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
  scale_y_continuous(breaks = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                    ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                     labels = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                    ceiling(  (max(dat$A_up)+11) /10)*10,10 )
  ) +
  facet_wrap(~group ,ncol=2, scales = "free_y") + 
geom_blank(aes(y = y_min)) + geom_blank(aes(y = y_max))

Так что здесь я использую data.table by = group создавать y_min а также y_max для каждой группы. И затем использовать эти значения в geom_blank расширить площадь участка.

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

Очевидно, это автоматически масштабируется до любого количества групп / аспектов.

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

Сначала я создаю функцию для расчета разрывов. (Это функция, которую вы бы изменили, если вы хотите использовать разные шкалы для разных диапазонов.)

myBreaks <- function(x){
  seq(floor( (min(x) )  /10)*10 ,
      ceiling( (max(x) ) /10)*10,
      10 )
}

Затем используйте lapply составить график из подмножества ваших данных для каждой группы:

sepPlots <- lapply(levels(dat$group), function(thisGroup){

  ggplot(data= dat[dat$group == thisGroup, ],
         aes(x=as.factor(x), y=A, group = 1)) +
    geom_line()  + geom_point() + 
    geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
    scale_y_continuous(breaks = myBreaks,
                       limits = range(myBreaks(dat[dat$group == thisGroup, c("A_up", "A_low")]))
                       ) +
    facet_wrap(~group)
})

Обратите внимание, что я все еще использовал facet_wrap для того, чтобы получить stripназвание стиля над сюжетом, хотя вы можете просто использовать ggtitle вместо этого, если вам нравится этот стиль лучше.

Затем используйте plot_grid от cowplot чтобы сшить все обратно вместе. Обратите внимание, что если вы загружаете cowplot он устанавливает свою собственную тему по умолчанию. Чтобы вернуться назад, используйте theme_set(theme_gray())

cowplot::plot_grid(plotlist = sepPlots)

дает

cowplot довольно хорошо задокументировано, поэтому вы сможете вносить коррективы в сюжет по мере необходимости, когда вы увеличиваете количество групп.

У меня не установлен ggplot, но может быть простой if () else может решить вашу проблему. Моя первая попытка будет такой:

if {
(dat$group =="y") c( floor(  min(dat$A_low[dat$group =="y"])  /10)*10, ceiling(max(dat$A_up[dat$group =="y"])/10)*10 )

else c( floor(  min(dat$A_low[dat$group =="z"])  /10)*10,     ceiling(max(dat$A_up[dat$group =="z"])/10)*10 )
}
Другие вопросы по тегам