【问题标题】:Changing the relative height of the bins of a histogram interactively以交互方式更改直方图 bin 的相对高度
【发布时间】:2011-06-16 00:16:58
【问题描述】:

在主观概率评估中,需要引出受试者相信的分布。这可以通过让主体操纵直方图的每个频率区间的相对高度来实现。即概率的分布,包络曲线的形状保持累积和(P_i)=1。 这怎么能用 R 来完成?是否已经有可以构建的软件包?


或者:如何在电子表格应用程序(excel、oo calc、google 电子表格)中完成?

【问题讨论】:

    标签: user-interface r histogram cumulative-frequency


    【解决方案1】:

    这是我使用 tkrplot 包和可选的 logspline 包放在一起的一些代码。

    只需运行函数(您可以更改参数,但要进行测试,您可以使用默认值进行测试)然后在出现的新窗口中单击绘图,左键单击将添加一个单击点,右 (或中间)点击将删除最接近您点击的点。

    我可能会稍微清理一下,并将其包含在 TeachingDemos 包的未来版本中(因此非常欢迎 cmets/建议)。

    TkBuildDist <- function(  x=seq(min+(max-min)/nbin/2,
                                    max-(max-min)/nbin/2,
                                    length.out=nbin),
                              min=0, max=10, nbin=10, logspline=TRUE,
                              intervals=FALSE) {
    
        if(logspline) logspline <- require(logspline)
        require(tkrplot)
    
        xxx <- x
    
        brks <- seq(min, max, length.out=nbin+1)
        nx <- seq( min(brks), max(brks), length.out=250 )
    
        lx <- ux <- 0
        first <- TRUE
    
        replot <- if(logspline) {
            if(intervals) {
                function() {
                    hist(xxx, breaks=brks, probability=TRUE,xlab='', main='')
                    xx <- cut(xxx, brks, labels=FALSE)
                    fit <- oldlogspline( interval = cbind(brks[xx], brks[xx+1]) )
                    lines( nx, doldlogspline(nx,fit), lwd=3 )
                    if(first) {
                        first <<- FALSE
                        lx <<- grconvertX(min, to='ndc')
                        ux <<- grconvertX(max, to='ndc')
                    }
                }
            } else {
                function() {
                    hist(xxx, breaks=brks, probability=TRUE,xlab='', main='')
                    fit <- logspline( xxx )
                    lines( nx, dlogspline(nx,fit), lwd=3 )
                    if(first) {
                        first <<- FALSE
                        lx <<- grconvertX(min, to='ndc')
                        ux <<- grconvertX(max, to='ndc')
                    }
                }
            }
        } else {
            function() {
                hist(xxx, breaks=brks, probability=TRUE,xlab='',main='')
                if(first) {
                    first <<- FALSE
                    lx <<- grconvertX(min, to='ndc')
                    ux <<- grconvertX(max, to='ndc')
                }
            }
        }
    
        tt <- tktoplevel()
        tkwm.title(tt, "Distribution Builder")
    
        img <- tkrplot(tt, replot, vscale=1.5, hscale=1.5)
        tkpack(img, side='top')
    
        tkpack( tkbutton(tt, text='Quit', command=function() tkdestroy(tt)),
               side='right')
    
        iw <- as.numeric(tcl('image','width',tkcget(img,'-image')))
    
        mouse1.down <- function(x,y) {
            tx <- (as.numeric(x)-1)/iw
            ux <- (tx-lx)/(ux-lx)*(max-min)+min
            xxx <<- c(xxx,ux)
            tkrreplot(img)
        }
    
        mouse2.down <- function(x,y) {
            if(length(xxx)) {
                tx <- (as.numeric(x)-1)/iw
                ux <- (tx-lx)/(ux-lx)*(max-min)+min
                w <- which.min( abs(xxx-ux) )
                xxx <<- xxx[-w]
                tkrreplot(img)
            }
        }
    
        tkbind(img, '<ButtonPress-1>', mouse1.down)
        tkbind(img, '<ButtonPress-2>', mouse2.down)
        tkbind(img, '<ButtonPress-3>', mouse2.down)
    
        tkwait.window(tt)
    
        out <- list(x=xxx)
        if(logspline) {
            if( intervals ) {
                xx <- cut(xxx, brks, labels=FALSE)
                out$logspline <- oldlogspline( interval = cbind(brks[xx], brks[xx+1]) )
            } else {
                out$logspline <- logspline(xxx)
            }
        }
    
        if(intervals) {
            out$intervals <- table(cut(xxx, brks))
        }
    
        out$breaks <- brks
    
        return(out)
    }
    

    这是另一个允许拖动条形高度的版本:

    TkBuildDist2 <- function( min=0, max=1, nbin=10, logspline=TRUE) {
        if(logspline) logspline <- require(logspline)
        require(tkrplot)
    
        xxx <- rep( 1/nbin, nbin )
    
        brks <- seq(min, max, length.out=nbin+1)
        nx <- seq( min, max, length.out=250 )
    
        lx <- ux <- ly <- uy <- 0
        first <- TRUE
    
        replot <- if(logspline) {
            function() {
                barplot(xxx, width=diff(brks), xlim=c(min,max), space=0,
                        ylim=c(0,0.5), col=NA)
                axis(1,at=brks)
                xx <- rep( 1:nbin, round(xxx*100) )
                capture.output(fit <- oldlogspline( interval = cbind(brks[xx], brks[xx+1]) ))
                lines( nx, doldlogspline(nx,fit)*(max-min)/nbin, lwd=3 )
    
                if(first) {
                    first <<- FALSE
                    lx <<- grconvertX(min, to='ndc')
                    ly <<- grconvertY(0,   to='ndc')
                    ux <<- grconvertX(max, to='ndc')
                    uy <<- grconvertY(0.5, to='ndc')
                }
            }
        } else {
            function() {
                barplot(xxx, width=diff(brks), xlim=range(brks), space=0,
                        ylim=c(0,0.5), col=NA)
                axis(at=brks)
                if(first) {
                    first <<- FALSE
                    lx <<- grconvertX(min, to='ndc')
                    ly <<- grconvertY(0,   to='ndc')
                    ux <<- grconvertX(max, to='ndc')
                    uy <<- grconvertY(0.5, to='ndc')
                }
            }
        }
    
        tt <- tktoplevel()
        tkwm.title(tt, "Distribution Builder")
    
        img <- tkrplot(tt, replot, vscale=1.5, hscale=1.5)
        tkpack(img, side='top')
    
        tkpack( tkbutton(tt, text='Quit', command=function() tkdestroy(tt)),
               side='right')
    
        iw <- as.numeric(tcl('image','width',tkcget(img,'-image')))
        ih <- as.numeric(tcl('image','height',tkcget(img,'-image')))
    
    
    
        md <- FALSE
    
        mouse.move <- function(x,y) {
            if(md) {
                tx <- (as.numeric(x)-1)/iw
                ty <- 1-(as.numeric(y)-1)/ih
    
                w <- findInterval(tx, seq(lx,ux, length=nbin+1))
    
                if( w > 0 && w <= nbin && ty >= ly && ty <= uy ) {
                     xxx[w] <<- 0.5*(ty-ly)/(uy-ly)
                    xxx[-w] <<- (1-xxx[w])*xxx[-w]/sum(xxx[-w])
    
                    tkrreplot(img)
                }
            }
        }
    
        mouse.down <- function(x,y) {
            md <<- TRUE
            mouse.move(x,y)
        }
    
        mouse.up <- function(x,y) {
            md <<- FALSE
        }
    
        tkbind(img, '<Motion>', mouse.move)
        tkbind(img, '<ButtonPress-1>', mouse.down)
        tkbind(img, '<ButtonRelease-1>', mouse.up)
    
        tkwait.window(tt)
    
        out <- list(breaks=brks, probs=xxx)
        if(logspline) {
            xx <- rep( 1:nbin, round(xxx*100) )
            out$logspline <- oldlogspline( interval = cbind(brks[xx], brks[xx+1]) )
        }
    
        return(out)
    }
    

    【讨论】:

    • 太棒了!非常直观和流畅。请注意,我认为您的意思是函数参数中的“nbin”,而不是“nbins”。
    • Roo,我使用概率 = TRUE 制作直方图并包含对数样条的原因是为了在视觉上看到相对频率。是的,我们是按单个单位添加的,但是在视觉上,当您增加一个部分时,所有其他部分都会减少,因此整体面积保持为 1。您能否详细说明您设想的界面是什么样的?
    • 它实现了所描述的功能。在 Ubuntu 上不工作,在 Windows Vista 上工作。明天我在 Ubuntu 上再试一次。最后一点是如果您可以拖动一个垃圾箱,以便您自动从所有其他垃圾箱中删除与您在该垃圾箱上不断增加的数量相同的数量。只有这样,您才能微调主观概率预期。谢谢
    • 好的,我添加了另一个允许拖动条的版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    相关资源
    最近更新 更多