首页 文章

绘制具有不同大小的箱的概率热图/ hexbin

提问于
浏览
14

这与另一个问题有关:Plot weighted frequency matrix .

我有这个图形(由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)

我非常喜欢这个绘图的构建方式,并且显示更频繁的路径比稀有路径更暗(但对于打印演示来说还不够清晰) . 我想做的是为数字生成某种hexbin或热图 . 考虑到这一点,似乎情节必须包含不同大小的垃圾箱(请参阅我的信封草图背面):

binsketch

那我的问题是: If I simulate a million runs using the code above, how can I present it as a heatmap or hexbin, with the different sized bins as shown in the sketch?

澄清:我不想依靠透明度来表明审判通过部分情节的罕见性 . 相反,我想用热来表示稀有,并表现出一条共同的路径,如热(红色)和罕见的路径,如冷(蓝色) . 此外,我不认为垃圾箱应该是相同的大小,因为第一次试验只有两个路径可以,但最后一个有更多 . 因此,我根据这一事实选择了更改箱秤 . Essentially I am counting the number of times a path passes through the cell (2 in col 1, 3 in col 2 etc) and then colouring the cell based on how many times it has been passed through.

更新:我已经有一个类似于@Andrie的情节,但我不确定它比顶级情节更清晰 . 这是图的不连续性,我不喜欢(为什么我想要某种热图) . 我认为,因为第一列只有两个可能的值,它们之间不应该存在巨大的视觉差距等等 . 因此我设想了不同大小的箱子 . 我仍然认为分档版本会更好地显示大量样本 .

plot2

更新:此website概述了绘制热图的过程:

要创建此密度(热图)版本,我们必须有效地枚举图像中每个离散位置的这些点的出现 . 这是通过设置网格并计算点坐标“落入”该网格中每个位置的每个单独像素“区间”的次数来完成的 .

也许该网站上的一些信息可以与我们已经拥有的信息相结合?

更新:我接受了Andrie写的一些内容question,以达到这一点,这与我的想法非常接近:
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

    Edit

    我认为以下解决方案可以满足您的要求 .

    (注意这很慢,特别是 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

    仅供参考:这是一个扩展的评论而不是一个答案 .

    对我来说,这个新的情节看起来像一个堆叠的条形图,其中每个条形的高度等于下一次试验中上下线的交点 .

    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个箱子 . 所以我们需要找出每个bin的倍数 .

    让我们作弊并将最后两列除以2,我们从视觉检查中得知最小值低于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.
    

    最明确的方法是分别创建每个bin . 显然,这可以在以后自动完成 . 记住每一点都是

    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")
    

相关问题