【问题标题】:three-way color gradient fill in rr中的三向颜色渐变填充
【发布时间】:2012-07-31 09:42:20
【问题描述】:

如何将三向颜色渐变(热图)填充到三图(三角形图),像这样。

plot(NA,NA,xlim=c(0,1),ylim=c(0,sqrt(3)/2),asp=1,bty="n",axes=F,xlab="",ylab="")
segments(0,0,0.5,sqrt(3)/2)
segments(0.5,sqrt(3)/2,1,0)
segments(1,0,0,0)

颜色应该与 triplot 并行运行。

【问题讨论】:

    标签: r plot triplot


    【解决方案1】:

    这是一种方法 - 这有点像 hack,使用点来逐个绘制渐变:

    plot(NA,NA,xlim=c(0,1),ylim=c(0,1),asp=1,bty="n",axes=F,xlab="",ylab="")
    segments(0,0,0.5,sqrt(3)/2)
    segments(0.5,sqrt(3)/2,1,0)
    segments(1,0,0,0)
    # sm - how smooth the plot is. Higher values will plot very slowly
    sm <- 500
    for (y in 1:(sm*sqrt(3)/2)/sm){
        for (x in (y*sm/sqrt(3)):(sm-y*sm/sqrt(3))/sm){
            ## distance from base line:
            d.red = y
            ## distance from line y = sqrt(3) * x:
            d.green = abs(sqrt(3) * x - y) / sqrt(3 + 1)
            ## distance from line y = - sqrt(3) * x + sqrt(3):
            d.blue = abs(- sqrt(3) * x - y + sqrt(3)) / sqrt(3 + 1)
            points(x, y, col=rgb(1-d.red,1 - d.green,1 - d.blue), pch=19)
        }
    }
    

    还有输出:

    您想使用这些渐变来表示数据吗?如果是这样,可以更改d.redd.greend.blue 来做到这一点——不过我还没有测试过类似的东西。我希望这会有所帮助,但例如使用 colorRamp 的适当解决方案可能会更好。

    编辑:根据 baptiste 的建议,这就是您将信息存储在向量中并一次性绘制出来的方式。它要快得多(尤其是sm 设置为 500,例如):

    plot(NA,NA,xlim=c(0,1),ylim=c(0,1),asp=1,bty="n",axes=F,xlab="",ylab="")
    sm <- 500
    x <- do.call(c, sapply(1:(sm*sqrt(3)/2)/sm, 
                           function(i) (i*sm/sqrt(3)):(sm-i*sm/sqrt(3))/sm))
    y <- do.call(c, sapply(1:(sm*sqrt(3)/2)/sm, 
                           function(i) rep(i, length((i*sm/sqrt(3)):(sm-i*sm/sqrt(3))))))
    d.red = y
    d.green = abs(sqrt(3) * x - y) / sqrt(3 + 1)
    d.blue = abs(- sqrt(3) * x - y + sqrt(3)) / sqrt(3 + 1)
    points(x, y, col=rgb(1-d.red,1 - d.green,1 - d.blue), pch=19)
    

    【讨论】:

    • 感谢您的出色解决方案...有没有办法从更深的颜色(红色、绿色和蓝色)开始,使渐变看起来更清晰
    • 我尝试了几种不同的方法来使渐变更清晰,但我找不到一种不会使图形区域变得非常黑暗和沉闷的方法。红色、绿色和蓝色从角落开始,你还好吗?如果是,请尝试将最后一行代码替换为 points(x, y, col=rgb(d.red,d.green,d.blue), pch=19) - 这三种颜色的渐变看起来更清晰,因为它们与其他颜色的原点混合不多。
    • 为什么要单独绘制每个点?您可以存储颜色向量并一次绘制所有点。
    • @baptiste - 感谢您指出这一点。我包含了一个使用向量的版本,它运行得更快。谢谢!
    【解决方案2】:

    这是一个带有光栅化背景图像的解决方案。 tricol 函数的sharpness 参数控制颜色变黑的速度。将其设置为 1 为您提供 Edward 的颜色,将其设置为 2 为您提供以下颜色。

    # Coordinates of the triangle
    tri <- rbind(sin(0:2*2/3*pi), cos(0:2*2/3*pi))
    
    # Function for calculating the color of a set of points `pt`
    # in relation to the triangle
    tricol <- function(pt, sharpness=2){
        require(splancs)
        RGB <- sapply(1:3, function(i){
            a <- sweep(pt, 2, tri[,i])
            b <- apply(tri[,-i], 1, mean) - tri[,i]
            sharpness*((a %*% b) / sum(b^2))-sharpness+1
        })
        RGB[-inpip(pt,t(tri)),] <- 1    # Color points outside the triangle white
        do.call(rgb, unname(as.data.frame(pmin(pmax(RGB, 0), 1))))
    }
    
    # Plot
    res <- 1000                         # Resolution
    xi <- seq(-1, 1, length=res)        # Axis points
    yi <- seq(-.8, 1.2, length=res)
    x <- xi[1] + cumsum(diff(xi))       # Midpoints between axis points
    y <- yi[1] + cumsum(diff(yi))
    xy <- matrix(1:(length(x)*length(y)), length(x))
    image(xi, yi, xy, col=tricol(as.matrix(expand.grid(x,y))), useRaster=TRUE)
    lines(tri[1,c(1:3,1)], tri[2,c(1:3,1)], type="l")
    

    tricol() 所做的是用颜色(红、绿、蓝)表示i 的每个角。它定义了从角到pt 中的点的向量矩阵a 和从角到对边中心的向量b。然后它将a 投影到b 上并缩放以获得相对距离= 颜色强度(并使用sharpness 应用一个小技巧来稍微调整颜色)。当涉及到像这个简单的代数这样的问题时,它可以发挥神奇的作用。

    由于混叠,您会在边缘周围产生一点噪点,但您可能可以将其调整掉,或者在三角形中画出稍宽的线条。

    【讨论】:

    • 我正在考虑一个类似的想法,但在三角形的一侧有三个半径为 (R,G,B) 的圆盘,并且 alpha 通道逐渐变为 0。我相信 R 会做颜色自动混合。
    • 有点。它会显示哪个圆圈被画在哪个圆圈之上。假设红色在顶部,然后是绿色,然后是蓝色。在中间你会有 50% 的红色,但只有 25% 的绿色(剩余 50% 的 50%)和 12.5% 的蓝色。我见过的几乎每一个维恩图都受此影响,一旦我看到它,我就无法停止注意到它。 Take these for instance.
    【解决方案3】:

    这是我为 phonR 包设计的一个实现... fillTriangle 函数未导出,因此您必须使用 ::: 运算符来访问它。示例显示了基于 pch 和基于光栅的方法。

    # set up color scale
    colmap <- plotrix::color.scale(x=0:100, cs1=c(0, 180), cs2=100, cs3=c(25, 100),
                                   alpha=1, color.spec='hcl')
    # specify triangle vertices and corner colors
    vertices <- matrix(c(1, 4, 2, 1, 3, 4, length(colmap), 1, 30), nrow=3,
                       dimnames=list(NULL, c("x", "y", "z")))
    # edit next line to change density / resolution
    xseq <- yseq <- seq(0, 5, 0.01)
    grid <- expand.grid(x=xseq, y=yseq)
    grid$z <- NA
    grid.indices <- splancs::inpip(grid, vertices[,1:2], bound=FALSE)
    grid$z[grid.indices] <- with(grid[grid.indices,], 
                                 phonR:::fillTriangle(x, y, vertices))
    # plot it
    par(mfrow=c(1,2))
    # using pch
    with(grid, plot(x, y, col=colmap[round(z)], pch=16))
    # overplot original triangle
    segments(vertices[,1], vertices[,2], vertices[c(2,3,1),1], 
             vertices[c(2,3,1),2])
    points(vertices[,1:2], pch=21, bg=colmap[vertices[,3]], cex=2)
    
    # using raster
    image(xseq, yseq, matrix(grid$z, nrow=length(xseq)), col=colmap)
    # overplot original triangle
    segments(vertices[,1], vertices[,2], vertices[c(2,3,1),1], 
             vertices[c(2,3,1),2])
    points(vertices[,1:2], pch=21, bg=colmap[vertices[,3]], cex=2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      • 2014-01-31
      • 2018-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      相关资源
      最近更新 更多