Как построить две гистограммы вместе в R?

Я использую R и у меня есть два кадра данных: морковь и огурцы. Каждые данные В фрейме есть один числовой столбец, в котором указана длина всех измеренных морковей (всего: 100 тыс. моркови) и огурцов (всего: 50 тыс. огурцов).

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

что-то вроде этого было бы неплохо, но я не понимаю, как создать его из моих двух таблиц:

overlapped density

211
задан Lenna 9 January 2014 в 06:32
поделиться

5 ответов

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

Если вы читали о ggplot, возможно, единственное, чего вам не хватает, - это объединения двух фреймов данных в один длинный.

Итак, давайте начнем с того, что у вас есть, двух отдельных наборов данных и объединим их.

carrots <- data.frame(length = rnorm(100000, 6, 2))
cukes <- data.frame(length = rnorm(50000, 7, 2.5))

# Now, combine your two dataframes into one.  
# First make a new column in each that will be 
# a variable to identify where they came from later.
carrots$veg <- 'carrot'
cukes$veg <- 'cuke'

# and combine into your new data frame vegLengths
vegLengths <- rbind(carrots, cukes)

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

ggplot(vegLengths, aes(length, fill = veg)) + geom_density(alpha = 0.2)

enter image description here

Теперь, если вам действительно нужны гистограммы, следующее будет работать. Обратите внимание, что вы должны изменить позицию аргумента «стек» по умолчанию. Вы можете пропустить это, если действительно не представляете, как должны выглядеть ваши данные. Там более высокая альфа выглядит лучше. Также обратите внимание, что я сделал это гистограммы плотности. Легко удалить y = ... плотность .. , чтобы вернуть его к счетчикам.

ggplot(vegLengths, aes(length, fill = veg)) + 
   geom_histogram(alpha = 0.5, aes(y = ..density..), position = 'identity')

enter image description here

188
ответ дан 23 November 2019 в 04:32
поделиться

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

plotOverlappingHist <- function(a, b, colors=c("white","gray20","gray50"),
                                breaks=NULL, xlim=NULL, ylim=NULL){

  ahist=NULL
  bhist=NULL

  if(!(is.null(breaks))){
    ahist=hist(a,breaks=breaks,plot=F)
    bhist=hist(b,breaks=breaks,plot=F)
  } else {
    ahist=hist(a,plot=F)
    bhist=hist(b,plot=F)

    dist = ahist$breaks[2]-ahist$breaks[1]
    breaks = seq(min(ahist$breaks,bhist$breaks),max(ahist$breaks,bhist$breaks),dist)

    ahist=hist(a,breaks=breaks,plot=F)
    bhist=hist(b,breaks=breaks,plot=F)
  }

  if(is.null(xlim)){
    xlim = c(min(ahist$breaks,bhist$breaks),max(ahist$breaks,bhist$breaks))
  }

  if(is.null(ylim)){
    ylim = c(0,max(ahist$counts,bhist$counts))
  }

  overlap = ahist
  for(i in 1:length(overlap$counts)){
    if(ahist$counts[i] > 0 & bhist$counts[i] > 0){
      overlap$counts[i] = min(ahist$counts[i],bhist$counts[i])
    } else {
      overlap$counts[i] = 0
    }
  }

  plot(ahist, xlim=xlim, ylim=ylim, col=colors[1])
  plot(bhist, xlim=xlim, ylim=ylim, col=colors[2], add=T)
  plot(overlap, xlim=xlim, ylim=ylim, col=colors[3], add=T)
}

Вот другой способ сделать это, используя поддержку прозрачных цветов в R

a=rnorm(1000, 3, 1)
b=rnorm(1000, 6, 1)
hist(a, xlim=c(0,10), col="red")
hist(b, add=T, col=rgb(0, 1, 0, 0.5) )

Результаты в конечном итоге выглядят примерно так: alt text

41
ответ дан 23 November 2019 в 04:32
поделиться

Вот еще более простое решение, использующее базовую графику и альфа-смешивание (которое работает не на всех графических устройствах):

set.seed(42)
p1 <- hist(rnorm(500,4))                     # centered at 4
p2 <- hist(rnorm(500,6))                     # centered at 6
plot( p1, col=rgb(0,0,1,1/4), xlim=c(0,10))  # first histogram
plot( p2, col=rgb(1,0,0,1/4), xlim=c(0,10), add=T)  # second

Ключевым моментом является то, что цвета полупрозрачны.

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

enter image description here

248
ответ дан 23 November 2019 в 04:32
поделиться

Вот версия, подобная ggplot2, которую я дал только в базе R. Я скопировал кое-что из @nullglob.

генерировать данные

carrots <- rnorm(100000,5,2)
cukes <- rnorm(50000,7,2.5)

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

## calculate the density - don't plot yet
densCarrot <- density(carrots)
densCuke <- density(cukes)
## calculate the range of the graph
xlim <- range(densCuke$x,densCarrot$x)
ylim <- range(0,densCuke$y, densCarrot$y)
#pick the colours
carrotCol <- rgb(1,0,0,0.2)
cukeCol <- rgb(0,0,1,0.2)
## plot the carrots and set up most of the plot parameters
plot(densCarrot, xlim = xlim, ylim = ylim, xlab = 'Lengths',
     main = 'Distribution of carrots and cucumbers', 
     panel.first = grid())
#put our density plots in
polygon(densCarrot, density = -1, col = carrotCol)
polygon(densCuke, density = -1, col = cukeCol)
## add a legend in the corner
legend('topleft',c('Carrots','Cucumbers'),
       fill = c(carrotCol, cukeCol), bty = 'n',
       border = NA)

enter image description here

16
ответ дан 23 November 2019 в 04:32
поделиться

Вот пример того, как вы можете сделать это в «классической» R-графике:

## generate some random data
carrotLengths <- rnorm(1000,15,5)
cucumberLengths <- rnorm(200,20,7)
## calculate the histograms - don't plot yet
histCarrot <- hist(carrotLengths,plot = FALSE)
histCucumber <- hist(cucumberLengths,plot = FALSE)
## calculate the range of the graph
xlim <- range(histCucumber$breaks,histCarrot$breaks)
ylim <- range(0,histCucumber$density,
              histCarrot$density)
## plot the first graph
plot(histCarrot,xlim = xlim, ylim = ylim,
     col = rgb(1,0,0,0.4),xlab = 'Lengths',
     freq = FALSE, ## relative, not absolute frequency
     main = 'Distribution of carrots and cucumbers')
## plot the second graph on top of this
opar <- par(new = FALSE)
plot(histCucumber,xlim = xlim, ylim = ylim,
     xaxt = 'n', yaxt = 'n', ## don't add axes
     col = rgb(0,0,1,0.4), add = TRUE,
     freq = FALSE) ## relative, not absolute frequency
## add a legend in the corner
legend('topleft',c('Carrots','Cucumbers'),
       fill = rgb(1:0,0,0:1,0.4), bty = 'n',
       border = NA)
par(opar)

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

24
ответ дан 23 November 2019 в 04:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: