Самый простой способ дискретизировать непрерывные шкалы для цветовых шкал ggplot2?

Предположим, у меня есть такой сюжет:

ggplot(iris) + geom_point(aes(x=Sepal.Width, y=Sepal.Length, colour=Sepal.Length)) + scale_colour_gradient()

каков правильный способ дискретизации цветовой шкалы, например график, показанный ниже принятого ответа здесь (градиент разрывается на графике ggplot stat_bin2d)?

ggplot правильно распознает дискретные значения и использует для них дискретные шкалы, но мой вопрос в том, если у вас есть непрерывные данные и вам нужна дискретная цветная полоса для них (с каждым квадратом, соответствующим значению, и квадратами, окрашенными в градиент), что такое лучший способ сделать это? Должна ли дискретизация / биннинг происходить за пределами ggplot и помещаться в фрейм данных как отдельный столбец с дискретными значениями, или есть способ сделать это в ggplot? пример того, что я ищу, похож на показанный здесь масштаб: введите описание изображения здесь

за исключением того, что я рисую диаграмму рассеяния, а не что-то вроде geom_tile / heatmap.

Благодарю.


person Community    schedule 18.07.2013    source источник
comment
взгляните на stackoverflow.com/questions/50506832/   -  person tjebo    schedule 11.07.2019


Ответы (2)


Решение немного сложнее, потому что вам нужен дискретный масштаб. В противном случае вы, вероятно, могли бы просто использовать round.

library(ggplot2)

bincol <- function(x,low,medium,high) {
  breaks <- function(x) pretty(range(x), n = nclass.Sturges(x), min.n = 1)

  colfunc <- colorRampPalette(c(low, medium, high))

  binned <- cut(x,breaks(x))

  res <- colfunc(length(unique(binned)))[as.integer(binned)]
  names(res) <- as.character(binned)
  res
}

labels <- unique(names(bincol(iris$Sepal.Length,"blue","yellow","red")))
breaks <- unique(bincol(iris$Sepal.Length,"blue","yellow","red"))
breaks <- breaks[order(labels,decreasing = TRUE)]
labels <- labels[order(labels,decreasing = TRUE)]


ggplot(iris) + 
  geom_point(aes(x=Sepal.Width, y=Sepal.Length,
                 colour=bincol(Sepal.Length,"blue","yellow","red")), size=4) +
  scale_color_identity("Sepal.Length", labels=labels, 
                       breaks=breaks, guide="legend")

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

person Roland    schedule 18.07.2013
comment
Работает ли порядок этикеток, если в переменной, используемой для раскраски, существуют отрицательные числа? - person W7GVR; 28.10.2015

Вы можете попробовать следующее, у меня есть ваш пример кода, соответствующим образом измененный ниже:

#I am not so great at R, so I'll just make a data frame this way
#I am convinced there are better ways. Oh well.
df<-data.frame()
for(x in 1:10){
  for(y in 1:10){
    newrow<-c(x,y,sample(1:1000,1))
    df<-rbind(df,newrow)
  }
}
colnames(df)<-c('X','Y','Val')


#This is the bit you want
p<- ggplot(df, aes(x=X,y=Y,fill=cut(Val, c(0,100,200,300,400,500,Inf))))
p<- p + geom_tile() + scale_fill_brewer(type="seq",palette = "YlGn")
p<- p + guides(fill=guide_legend(title="Legend!"))

#Tight borders
p<- p + scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))
p

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

Результат выглядит следующим образом.

2D тепловая карта с дискретным цветом

person Richard    schedule 06.08.2015
comment
Мне это нравится, но мне интересно, есть ли способ пометить шкалу, как в примере, показанном в вопросе. Точнее: как добиться появления крайностей в точках отсечения между цветовыми слоями? - person W7GVR; 20.04.2017