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

Как рисовать стрелку на гистограмме, нарисованной с помощью ggplot2?

Вот набор данных:

   set.seed(123)
    myd <- data.frame (class = rep(1:4, each = 100), yvar = rnorm(400, 50,30))
    require(ggplot2)
    m <- ggplot(myd, aes(x = yvar))
    p <- m + geom_histogram(colour = "grey40", fill = "grey40", binwidth = 10)  +
       facet_wrap(~class) + theme_bw( ) 
    p + opts(panel.margin=unit(0 ,"lines"))

Я хочу добавить метки в бары, к которым относится каждый предметный класс, и создать что-то вроде обработанного графа пост-powerpoint. Есть ли способ сделать это в R?......

Изменить: мы можем думать о разных указателях, таких как точка или панель ошибок, если стрелка не невозможна.

enter image description here

Скажем, следующие предметы должны быть помечены:

class   name       yvar
2       subject4    104.0
3       subject3    8.5
3       subject1    80.0
4       subject2    40.0
4       subject1    115.0

classd <- data.frame (class = c(2,3,3,4,4), 
 name = c  ("subject4", "subject3", "subject1", "subject2", "subject1"), 
 yvar = c(104.0, 8.5,80.0,40.0, 115.0))
4b9b3361

Ответ 1

Обновление opts устарело; Вместо этого используйте theme.

Немного расширив bdemarest response, я думаю, что это вычисляет высоты бара программно. Последние два столбца arrow_pos содержат соответствующую информацию: Freq - высота бара; xval в позиции x середины бара. Но все же некоторые ярлыки перекрывают полоски.

РЕДАКТИРОВАТЬ По умолчанию cut ограничивает свои интервалы как (b1, b2], тогда как это означает, что ggplot2 ограничивает свои интервалы в geom_histogram как [b1, b2). Я изменил код так, чтобы оба привязали их интервалы как [b1, b2), т.е. Путь ggplot.

library(ggplot2)
library(grid) # unit() is in the grid package.
library(plyr)  # Data restructuring

set.seed(123)
myd <- data.frame (class = rep(1:4, each = 100), yvar = rnorm(400, 50, 30))

arrow_pos = read.table(header=TRUE, stringsAsFactors=FALSE,
                       text="class   name       yvar
                             2       subject4    104.0
                             3       subject3    8.5
                             3       subject1    80.0
                             4       subject2    40.0
                             4       subject1    115.0")

# Calculate the y positions for the labels and arrows
# For the myd data frame, obtain counts within each bin, but separately for each class
bwidth <- 10   # Set binwidth
Min <- floor(min(myd$yvar)/bwidth) * bwidth
Max <- ceiling(max(myd$yvar)/bwidth) * bwidth

# Function to do the counting
func <- function(df) {
   tab = as.data.frame(table(cut(df$yvar, breaks = seq(Min, Max, bwidth), right = FALSE)))
   tab$upper = Min + bwidth * (as.numeric(rownames(tab)))
   return(tab)
   }

# Apply the function to each class in myd data frame
TableOfCounts <- ddply(myd, .(class), function(df) func(df))

# Transfer counts of arrow_pos
arrow_pos$upper <- (floor(arrow_pos$yvar/bwidth) * bwidth) + bwidth
arrow_pos <- merge(arrow_pos, TableOfCounts, by = c("class", "upper"))
arrow_pos$xvar <- (arrow_pos$upper - .5 * bwidth)      # x position of the arrow is at the midpoint of the bin
arrow_pos$class=factor(as.character(arrow_pos$class),
    levels=c("1", "2", "3", "4")) # Gets rid of warnings.

ggplot(myd, aes(x=yvar)) +
     theme_bw() +
     geom_histogram(colour="grey70", fill="grey70", binwidth=bwidth) +
     facet_wrap(~ class) +
     theme(panel.margin=unit(0, "lines")) +
     geom_text(data=arrow_pos, aes(label=name, x=xvar, y=Freq + 2), size=4) +
     geom_segment(data=arrow_pos, 
                  aes(x=xvar, xend=xvar, y=Freq + 1.5, yend=Freq + 0.25),
                  arrow=arrow(length=unit(2, "mm")))

enter image description here

Ответ 2

Вот частичное решение, использующее geom_text() для добавления меток и geom_segment() с опцией arrow для добавления стрелок.

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

set.seed(123)
myd <- data.frame (class = rep(1:4, each = 100), yvar = rnorm(400, 50,30))

library(ggplot2)
library(grid) # unit() is in the grid package.

arrow_pos = read.table(header=TRUE, stringsAsFactors=FALSE,
                       text="class   name       yvar
                             2       subject4    104.0
                             3       subject3    8.5
                             3       subject1    80.0
                             4       subject2    40.0
                             4       subject1    115.0")

arrow_pos$y = c(3, 5, 9, 13, 1) # Manually enter y position.
arrow_pos$class = factor(as.character(arrow_pos$class),
    levels=c("1", "2", "3", "4")) # Gets rid of warnings.

p1 = ggplot(myd, aes(x=yvar)) +
     theme_bw() +
     geom_histogram(colour="grey40", fill="grey40", binwidth=10) +
     facet_wrap(~ class) +
     opts(panel.margin=unit(0 ,"lines")) +
     geom_text(data=arrow_pos, aes(label=name, x=yvar, y=y + 2), size=3) +
     geom_segment(data=arrow_pos, 
                  aes(x=yvar, xend=yvar, y=y + 1.5, yend=y + 0.25),
                  arrow=arrow(length=unit(2, "mm")))

png("p1.png", height=600, width=600)
print(p1)
dev.off()

enter image description here