Тепловая карта вероятности графика / гексбина с ячейками разных размеров - PullRequest
14 голосов
/ 05 сентября 2011

Это связано с другим вопросом: Матрица взвешенной частоты графика .

У меня есть этот рисунок (произведенный кодом ниже в R): multisample

#Set the number of bets and number of trials and % lines
numbet <- 36 
numtri <- 1000 
#Fill a matrix where the rows are the cumulative bets and the columns are the trials
xcum <- matrix(NA, nrow=numbet, ncol=numtri)
for (i in 1:numtri) {
x <- sample(c(0,1), numbet, prob=c(5/6,1/6), replace = TRUE)
xcum[,i] <- cumsum(x)/(1:numbet)
}
#Plot the trials as transparent lines so you can see the build up
matplot(xcum, type="l", xlab="Number of Trials", ylab="Relative Frequency", main="", col=rgb(0.01, 0.01, 0.01, 0.02), las=1)

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

binsketch

Тогда мой вопрос: Если я смоделирую миллион прогонов, используя приведенный выше код, как я могу представить его в виде тепловой карты или гексбина с ячейками разного размера, как показано на эскизе?

Чтобы уточнить: я не хочу полагаться на прозрачность, чтобы показать редкость испытания, проходящего через часть сюжета. Вместо этого я хотел бы обозначить редкость теплом и показать общий путь как горячий (красный) и редкий путь как холодный (синий). Кроме того, я не думаю, что корзины должны быть одинакового размера, потому что в первом испытании есть только два места, где может быть путь, но в последнем есть гораздо больше. Отсюда тот факт, что я выбрал изменяющуюся шкалу ящика, основываясь на этом факте. По сути, я подсчитываю, сколько раз путь проходит через ячейку (2 в столбце 1, 3 в столбце 2 и т. Д.), А затем окрашиваю ячейку в зависимости от того, сколько раз он был пройден.

ОБНОВЛЕНИЕ: у меня уже был сюжет, похожий на @Andrie, но я не уверен, что он намного яснее, чем верхний сюжет. Мне не нравится прерывистый характер этого графика (и почему я хочу какую-то тепловую карту). Я думаю, что поскольку в первом столбце есть только два возможных значения, между ними не должно быть огромного визуального разрыва и т. Д. И т. Д. Поэтому я и предусмотрел бункеры разных размеров. Я все еще чувствую, что биннинг-версия лучше показала бы большое количество образцов.

plot2

Обновление: Этот веб-сайт описывает процедуру построения тепловой карты:

Чтобы создать версию графика плотности (тепловой карты), мы должны эффективно перечислить появление этих точек в каждом отдельном месте на изображении. Это делается путем настройки сетки и подсчета количества раз, когда координата точки «попадает» в каждый из отдельных «бункеров» пикселей в каждом месте этой сетки.

Возможно, некоторую информацию на этом сайте можно объединить с тем, что у нас уже есть?

Обновление: я взял кое-что из того, что Андри написал с этим вопросом , чтобы прийти к этому, что довольно близко к тому, что я задумывал: heatmap

numbet <- 20
numtri <- 100
prob=1/6
#Fill a matrix 
xcum <- matrix(NA, nrow=numtri, ncol=numbet+1)
for (i in 1:numtri) {
  x <- sample(c(0,1), numbet, prob=c(prob, 1-prob), replace = TRUE)
  xcum[i, ] <- c(i, cumsum(x)/cumsum(1:numbet))
}
colnames(xcum) <- c("trial", paste("bet", 1:numbet, sep=""))

mxcum <- reshape(data.frame(xcum), varying=1+1:numbet, 
  idvar="trial", v.names="outcome", direction="long", timevar="bet")

 #from the other question
 require(MASS)
dens <- kde2d(mxcum$bet, mxcum$outcome)
filled.contour(dens)

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

Обновление: это похоже на другие графики здесь. Это не совсем верно:

hexbin

plot(hexbin(x=mxcum$bet, y=mxcum$outcome))

Последняя попытка. Как указано выше: enter image description here

image(mxcum$bet, mxcum$outcome)

Это очень хорошо. Мне бы хотелось, чтобы это выглядело как мой нарисованный от руки эскиз.

Ответы [ 2 ]

11 голосов
/ 14 сентября 2011

Редактировать

Я думаю, что следующее решение делает то, что вы просите.

(Обратите внимание, что это медленно, особенно шаг reshape)

numbet <- 32
numtri <- 1e5
prob=5/6
#Fill a matrix 
xcum <- matrix(NA, nrow=numtri, ncol=numbet+1)
for (i in 1:numtri) {
  x <- sample(c(0,1), numbet, prob=c(prob, 1-prob), replace = TRUE)
  xcum[i, ] <- c(i, cumsum(x)/cumsum(1:numbet))
}
colnames(xcum) <- c("trial", paste("bet", 1:numbet, sep=""))

mxcum <- reshape(data.frame(xcum), varying=1+1:numbet, 
  idvar="trial", v.names="outcome", direction="long", timevar="bet")


library(plyr)
mxcum2 <- ddply(mxcum, .(bet, outcome), nrow)
mxcum3 <- ddply(mxcum2, .(bet), summarize, 
                ymin=c(0, head(seq_along(V1)/length(V1), -1)), 
                ymax=seq_along(V1)/length(V1),
                fill=(V1/sum(V1)))
head(mxcum3)

library(ggplot2)

p <- ggplot(mxcum3, aes(xmin=bet-0.5, xmax=bet+0.5, ymin=ymin, ymax=ymax)) + 
    geom_rect(aes(fill=fill), colour="grey80") + 
    scale_fill_gradient("Outcome", formatter="percent", low="red", high="blue") +
    scale_y_continuous(formatter="percent") +
    xlab("Bet")

print(p)

enter image description here

3 голосов
/ 05 сентября 2011

К вашему сведению: это скорее расширенный комментарий, чем ответ.

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

enter image description here

Способ, которым я бы подошел к этому, состоит в том, чтобы рассматривать «Испытания» как категориальную переменную. Затем мы можем искать в каждой строке xcum элементы, которые равны. Если это так, то мы можем считать это точкой пересечения, минимумы которой также представляют кратное, определяющее высоту наших стержней.

x <- t(xcum)
x <- x[duplicated(x),]
x[x==0] <- NA

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

Trial 1 (2) = 1, 0.5 # multiple = 0.5
Trial 2 (3) = 1, 0.66, 0.33 #  multiple = 0.33
Trial 3 (4) = 1, 0.75, 0.5, 0.25 # multiple = 0.25
Trial 4 (5) = 1, 0.8,  0.6, 0.4, 0.2 # multiple = 0.2
Trial 5 (6) = 1, 0.8333335, 0.6666668, 0.5000001, 0.3333334, 0.1666667
... 
Trial 36 (35) = 1, 0.9722223, ..., 0.02777778 # mutiple = 0.05555556 / 2

Другими словами, для каждого испытания есть n-1 пункт для построения графика. На вашем рисунке у вас есть 7 корзин. Таким образом, мы должны выяснить, кратные для каждого бина.

Давайте обманем и разделим последние два столбца на два, мы знаем из визуального осмотра, что минимумы ниже 0,05

x[,35:36] <- x[,35:36] / 2

Затем найдите минимум каждого столбца:

x <- apply(x, 2, function(x) min(x, na.rm=T))[-1] # Drop the 1
x <- x[c(1,2,3,4,8,17,35)] # I'm just guessing here by the "look" of your drawing. 

Самый ясный способ сделать это - создать каждую корзину отдельно. Очевидно, это может быть сделано автоматически позже. Помня, что каждая точка

bin1 <- data.frame(bin = rep("bin1",2), Frequency = rep(x[1],2))
bin2 <- data.frame(bin = rep("bin2",3), Frequency = rep(x[2],3))
bin3 <- data.frame(bin = rep("bin3",4), Frequency = rep(x[3],4))
bin4 <- data.frame(bin = rep("bin4",5), Frequency = rep(x[4],5))
bin5 <- data.frame(bin = rep("bin5",9), Frequency = rep(x[5],9))
bin6 <- data.frame(bin = rep("bin6",18), Frequency = rep(x[6],18))
bin7 <- data.frame(bin = rep("bin7",36), Frequency = rep(x[7],36))

df <- rbind(bin1,bin2,bin3,bin4,bin5,bin6,bin7)
ggplot(df, aes(bin, Frequency, color=Frequency)) + geom_bar(stat="identity", position="stack")
...