Построение выровненных гистограмм на одном графике

#r

#r

Вопрос:

Мне нужно было бы построить выровненные гистограммы на одном графике из строк матрицы. В следующем примере мне нужно будет построить 5 сложенных гистограмм. Однако команда hist отображает одну гистограмму всей матрицы. Есть ли какое-нибудь обходное решение, которое я мог бы использовать?

Заранее спасибо.

Артуро

 x <- 10; y <- 10; g <- 5
dat <- matrix(rnorm((x   y) * g), ncol = x   y)
hist (dat)
 

Комментарии:

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

2. Это правильно. Каждая строка должна иметь свою собственную ось y и общую ось x.

Ответ №1:

ggplot сделайте это легко (для этого нужны данные длинной формы).

 library(tidyr); library(dplyr); library(ggplot2)

df <- dat %>% t() %>% as.data.frame() %>% gather(row)  # chage data into a long format
Breaks <- hist(dat, plot=F)$breaks                     # get (or decide) breaks

ggplot(df, aes(x = value, fill = row))   geom_histogram(position = "stack", breaks = Breaks)
 

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

[ОТРЕДАКТИРОВАНО]
Это то, что вы хотите?

   ## original
ggplot(df, aes(x = value))   
  geom_histogram(breaks = Breaks)  
  facet_wrap(~ row)            # make histogram par group.

  ## modified
ggplot(df, aes(x = value, fill = row))                   # change fill colour
  geom_histogram(breaks = Breaks)  
  facet_wrap(~ row, ncol = 1)                            # bring graphs into line
   #  facet_wrap( ~ row, ncol = 1, scales = "free_y")    # if you don't want fixed scale
  theme(strip.background = element_blank(), strip.text.x = element_blank()) # delete labels
 

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

[ОТРЕДАКТИРОВАНО 2: подход base_plot]
Базовый график экономит время.

  ## example data
x <- 1500; y <- 1500; g <- 30
set.seed(1); dat <- matrix(rnorm((x   y) * g), ncol = x   y)

 ## decide breaks
Breaks <- seq(-4.5, 4.5, 0.5)

 ## change par() to draw multiple graphs
par.old <- par(mar = c(0.1, 4.0, 0.1, 0.5), oma = c(4, 0, 0, 0), mfrow = c(nrow(dat), 1))

for(i in 1:nrow(dat)) {
  hist(dat[,i], breaks = Breaks, xaxt = "n", xlab = "", main = "")
#  grid(NULL)
    }
par(new=T)
hist(dat[,nrow(dat)], breaks = Breaks, main = "", yaxt = "n", 
     xlab = "x", ylab = "", border = NA)          # add x-axis

par(par.old)
 

Комментарии:

1. Спасибо, но мне нужно разделить каждую строку на моем графике, чтобы ее вклад был виден сразу

2. Спасибо. Это близко к тому, чего я хочу. Теперь мне нужно понять код .. 🙂

3. Также спасибо за прокомментированный код. У меня есть еще один вопрос, если вы не возражаете. Иногда мне нужно построить массивы размером до 30×6000, а не 5×20, как в приведенном мной примере. Я заметил, что в этом случае процедура занимает много времени. Я подумал, что, возможно, удаление цветов могло бы ускорить процесс. Считаете ли вы, что это было бы осуществимо?

4. @Arturo; К сожалению, насколько я знаю по своему опыту, цвета мало влияют на время. Конечно, вы можете удалить цвета гистограммы, удалив fill = row и изменив тему, просто вставив другую ggtheme раньше theme(strip...) , например, ... facet_wrap(~ row, ncol = 1) theme_minimal() theme(strip.background = element_blank(), strip.text.x = element_blank()) (см. ggtheme ). У меня нет хорошей идеи, как сэкономить время.

5. @Arturo; Я добавил другой подход.

Ответ №2:

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

Рассмотрим набор данных, в котором столбец x является непрерывной переменной, а столбец y — факторной переменной; на каждом уровне будет получена одна гистограмма. Ниже приведен пример кода с использованием ggplot2:

 OverlayedHist <- function(mData       ,
                          featureVar  ,
                          grouper     ,
                          mbinwidth   ,
                          mTitle      ,
                          mxlab       ,
                          mylab       ,
                          mlegendTitle
){

  # function name: OverlayedHist
  #       purpose: To produce overlayed histograms against a grouping variable
  #         Input: 
  #         mData: dataset object in data.table format
  #    featureVar: name of continuous variable to produce histogram
  #       grouper: the grouping variable to produce the histogram 
  #     mbinwidth: binwidth (see ggplot2 parameters)
  #        mTitle: Character to define title
  #         mxlab: Character to define xlab name
  #         mylab: Character to define ylab name
  #  mlegendTitle: Character to define legend title

  library(data.table)
  library(ggplot2)
  library(plotly)

  p <- ggplot(allDat, aes(eval(parse(text = featureVar)), fill = eval(parse(text = grouper))))  
    geom_histogram(alpha = 0.7, position = 'identity', binwidth = mbinwidth)   
    scale_fill_manual(values=c("#377EB8","#E41A1C"))   
    ggtitle(mTitle)  
    xlab(mxlab)   ylab(mylab)   
    guides(fill=guide_legend(title=mlegendTitle))   theme(plot.title = element_text(size=10))


  return(ggplotly(p))

}
 

Надеюсь, это поможет.

Приветствия! K.

Комментарии:

1. Не могли бы вы, пожалуйста, опубликовать какой-нибудь рабочий код для тестирования вашего метода?

2. Выше вы можете найти более подробную версию интерактивного сюжета