Подтвердить что ты не робот

Ggplot2: фигурные скобки на оси?

В отвечая на недавнюю визуализацию мне действительно нужны скобки, чтобы показать пролет на оси, и я не могу понять, как это сделать в ggplot2. Здесь сюжет:

example plot

Вместо метки, мне бы очень хотелось, чтобы метка оси y "Вторая буква двухбуквенных имен" имела брекет, простирающийся от 1 до 10 (вертикальный интервал красных и синих вторых букв). Но я не уверен, как это сделать. Ось х могла бы выиграть от подобного лечения.

Код доступен в связанном CrossValidated вопросе (и излишне сложный для этого примера, поэтому я его не покажу). Вместо этого здесь минимальный пример:

library(ggplot2)
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") )

minimal example

В этом случае скобка из (0,1) для низких типов и из (2,3) для высоких типов была бы идеальной, а не галочкой.

Я бы предпочел не использовать geom_rect, потому что:

  • Маркировка останется
  • Я бы предпочел скобки
  • Он будет внутри сюжета, а не вне его

Как бы я это сделал? Идеальный ответ:

  • Хорошая, гладкая, тонкая фигурная скобка
  • Выполняется за пределами области печати
  • Определяется с помощью аргумента высокого уровня (в идеале объект типа диапазона, переданный в опцию breaks в scale_x_continuous)
4b9b3361

Ответ 1

Обновление. Обязательно ознакомьтесь с этими связанными вопросами и ответами Stackoverflow, если вам нужно сохранить график с помощью ggsave() и сохранить скобки в сохраненном изображении.


ОП запросил кронштейн с участка. Это решение использует axis.ticks.length в сочетании с axis.ticks = element_blank() чтобы скобка была вне области построения графика. Этот ответ основывается на ответах @Pankil и @user697473: мы будем использовать пакет pBrackets R - и включим картинки!

library(ggplot2)
library(grid)
library(pBrackets) 
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
the_plot <- qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") ) +
  theme(axis.ticks = element_blank(),
        axis.ticks.length = unit(.85, "cm"))


#Run grid.locator a few times to get coordinates for the outer
#most points of the bracket, making sure the 
#bottom_y coordinate is just at the bottom of the gray area.
# to exit grid.locator hit esc; after setting coordinates
# in grid.bracket comment out grid.locator() line
the_plot
grid.locator(unit="native") 
bottom_y <- 284
grid.brackets(220, bottom_y,   80, bottom_y, lwd=2, col="red")
grid.brackets(600, bottom_y,  440, bottom_y, lwd=2, col="red")

enter image description here

Быстрая заметка о @Pankil:

## Bracket coordinates depend on the size of the plot
## for instance,
## Pankil suggested bracket coordinates do not work
## with the following sizing:
the_plot
grid.brackets(240, 440, 50, 440, lwd=2, col="red")
grid.brackets(570, 440, 381, 440, lwd=2, col="red")
## 440 seems to be off the graph...

enter image description here

И еще пара демонстрирует функциональность pBrackets:

#note, if you reverse the x1 and x2, the bracket flips:
the_plot
grid.brackets( 80, bottom_y, 220, bottom_y, lwd=2, col="red")
grid.brackets(440, bottom_y, 600, bottom_y, lwd=2, col="red")

enter image description here

## go vertical:
the_plot
grid.brackets(235, 200, 235, 300, lwd=2, col="red")
grid.brackets(445, 125, 445,  25, lwd=2, col="red")

enter image description here

Ответ 2

Другое решение, использующее функцию, которая рисует фигурные скобки.

Спасибо Гур!

curly <- function(N = 100, Tilt = 1, Long = 2, scale = 0.1, xcent = 0.5,
                  ycent = 0.5, theta = 0, col = 1, lwd = 1, grid = FALSE){

# N determines how many points in each curve
# Tilt is the ratio between the axis in the ellipse 
#  defining the curliness of each curve
# Long is the length of the straight line in the curly brackets 
#  in units of the projection of the curly brackets in this dimension
# 2*scale is the absolute size of the projection of the curly brackets 
#  in the y dimension (when theta=0)
# xcent is the location center of the x axis of the curly brackets
# ycent is the location center of the y axis of the curly brackets
# theta is the angle (in radians) of the curly brackets orientation
# col and lwd are passed to points/grid.lines

           ymin <- scale / Tilt
           y2 <- ymin * Long
           i <- seq(0, pi/2, length.out = N)

           x <- c(ymin * Tilt * (sin(i)-1),
                  seq(0,0, length.out = 2),
                  ymin * (Tilt * (1 - sin(rev(i)))),
                  ymin * (Tilt * (1 - sin(i))),
                  seq(0,0, length.out = 2),
                  ymin * Tilt * (sin(rev(i)) - 1))

           y <- c(-cos(i) * ymin,
                  c(0,y2),
                  y2 + (cos(rev(i))) * ymin,
                  y2 + (2 - cos(i)) * ymin,
                  c(y2 + 2 * ymin, 2 * y2 + 2 * ymin),
                  2 * y2 + 2 * ymin + cos(rev(i)) * ymin)

           x <- x + xcent
           y <- y + ycent - ymin - y2

           x1 <- cos(theta) * (x - xcent) - sin(theta) * (y - ycent) + xcent
           y1 <- cos(theta) * (y - ycent) + sin(theta) * (x - xcent) + ycent

           ##For grid library:
           if(grid){
              grid.lines(unit(x1,"npc"), unit(y1,"npc"),gp=gpar(col=col,lwd=lwd))
           }

           ##Uncomment for base graphics
           else{
              par(xpd=TRUE)
              points(x1,y1,type='l',col=col,lwd=lwd)
              par(xpd=FALSE)
           }

}


library(ggplot2)
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") )

curly(N=100,Tilt=0.4,Long=0.3,scale=0.025,xcent=0.2525,
      ycent=par()$usr[3]+0.1,theta=-pi/2,col="red",lwd=2,grid=TRUE)
curly(N=100,Tilt=0.4,Long=0.3,scale=0.025,xcent=0.8,
      ycent=par()$usr[3]+0.1,theta=-pi/2,col="red",lwd=2,grid=TRUE)

result plot

Ответ 3

Вот решение kludgy в ggplot, которое строит линейный рисунок, который смутно напоминает фигурные скобки.

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

bracket <- function(x, width, y, height){
  data.frame(
      x=(c(0,1,4,5,6,9,10)/10-0.5)*(width) + x,
      y=c(0,1,1,2,1,1,0)/2*(height) + y
  )
}

Перейдите к ggplot и, в частности, geom_line

qplot(x=x,y=y) +
    scale_x_continuous("",breaks=c(.5,2.5), labels=c("Low types","High types")) +
    geom_line(data=bracket(0.5,1,0,-0.2)) +
    geom_line(data=bracket(2.5,2,0,-0.2))

enter image description here

Ответ 4

как @user697473 предложил pBrackets - элегантное решение.

Он лучше всего работает с командами построения по умолчанию, но чтобы он работал с GGplot2, используйте pBracket::grid.brackets. Я включаю код, чтобы упростить его.

Начиная с вашего кода..

library(ggplot2)
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") ) +
  theme(axis.ticks = element_blank())

в последней строке удаляются тики, которые вам не нужны.
Теперь pBrackets

library(pBrackets)  # this will also load grid package
grid.locator(unit="native") 

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

grid.brackets(240, 440, 50, 440, lwd=2, col="red")
grid.brackets(570, 440, 381, 440, lwd=2, col="red")

Вы можете добавить скобки в любом месте графика или даже добавить текст, используя grid.text.

enter image description here

Надеюсь это поможет! Спасибо, pBrackets !

Pankil!