使用不同的“type”参数填充区域以匹配lattice中的线条

9

我知道可以使用latticeExtra中的panel.xyarea来填充图形的任何颜色区域。在xyplot中不定义type参数时,这样的填充将遵循默认的type="p"路线:

library(lattice)
library(latticeExtra)
data <- data.frame(time=1:24,value=rnorm(24))
xyplot(value~time, data, 
       panel=function(x,y,...){
             panel.xyarea(x,y,...)
             panel.xyplot(x,y,...)}) 

在此输入图片描述

这个图同时绘制了panel.xyareapanel.xyplot默认的type="p"的点。现在问题出现在当我想要改变绘制线条的type时,例如将其转换为阶梯函数type="S"

xyplot(value~time, data, type="S",
       panel=function(x,y,...){
             panel.xyarea(x,y,...)
             panel.xyplot(x,y,...)}

enter image description here

如上所示,在新的步函数下方,panel.xyarea并未填充该区域,而是将两个区域重叠绘制。如果我将type =“ S”移动到panel.xyarea中,则不会改变任何内容-实际上它根本不会注册type参数,并且绘制时就好像不存在一样。

有没有办法可以绕过此操作,使panel.xyarea填充我的图形,无论我定义的是什么类型 - 是步进函数(type =“ S”),还是loess(type =“ smooth” )或回归(type =“ r”)?或者在这种情况下有比panel.xyarea更好的东西可用吗?


不,没有简单且完全通用的方法可以做到这一点(而不修改许多不同的lattice函数)。您是否对于特定type=值的不完全通用(但简单)解决方案感兴趣? - Josh O'Brien
当然,让我们从某个地方开始,@Josh。 - Geek On Acid
好的,我会为 type="S"type="smooth" 分别提供几个快速示例。 - Josh O'Brien
1个回答

6
对于每个type的值,您需要构建一个自定义面板函数。幸运的是,如果您的函数紧密模仿现有的lattice代码(首先查看panel.xyplot),那么这不应该太难。例如,下面的两个自定义面板函数包含许多行代码,但只有几行(用注释标记)是我必须编写的。
一旦您定义了面板函数(从以下图表后面的代码块中复制它们),就可以像这样使用它们:
library(lattice)
library(latticeExtra)
library(gridExtra)
set.seed(100)
data <- data.frame(time=1:24,value=rnorm(24))

## Filled version of xyplot(..., type="S")
a <- xyplot(value~time, data, panel=panel.filled_S) 
## Filled version of xyplot(..., type="smooth") 
b <- xyplot(value~time, data, panel=panel.filled_smooth) 
grid.arrange(a, b, ncol = 2)

图片描述

对于填充版本的type="S"

## Modeled on code in panel.xyplot, which is called when type=S"
panel.filled_S <-
function(x,y, ...) {
    horizontal <- FALSE                  ## Edited (may not want to hardcode)
    ord <- if (horizontal)
        sort.list(y)
    else sort.list(x)
    n <- length(x)
    xx <- numeric(2 * n - 1)
    yy <- numeric(2 * n - 1)
    xx[2 * 1:n - 1] <- x[ord]
    yy[2 * 1:n - 1] <- y[ord]
    xx[2 * 1:(n - 1)] <- x[ord][-n]
    yy[2 * 1:(n - 1)] <- y[ord][-1]
    panel.xyarea(x = xx, y = yy, ...)    ## Edited
    panel.lines(x = xx, y = yy, ...)     ## Edited
}
xyplot(value~time, data, panel=panel.filled_S, type="o")

对于type="smooth"的填充版本:

## Modeled on code in panel.loess, called by panel.xyplot when type="smooth"
panel.filled_smooth <-
function (x, y, span = 2/3, degree = 1, family = c("symmetric",
    "gaussian"), evaluation = 50, lwd = plot.line$lwd, lty = plot.line$lty,
    col, col.line = plot.line$col, type, horizontal = FALSE,
    ..., identifier = "loess")
{
    x <- as.numeric(x)
    y <- as.numeric(y)
    ok <- is.finite(x) & is.finite(y)
    if (sum(ok) < 1)
        return()
    if (!missing(col)) {
        if (missing(col.line))
            col.line <- col
    }
    plot.line <- trellis.par.get("plot.line")
    if (horizontal) {
        smooth <- loess.smooth(y[ok], x[ok], span = span, family = family,
            degree = degree, evaluation = evaluation)
        panel.lines(x = smooth$y, y = smooth$x, col = col.line,
            lty = lty, lwd = lwd, ..., identifier = identifier)
        panel.xyarea(smooth$y, smooth$x, ...)  ## Edited
    }
    else {
        smooth <- loess.smooth(x[ok], y[ok], span = span, family = family,
            degree = degree, evaluation = evaluation)
        panel.lines(x = smooth$x, y = smooth$y, col = col.line,
            lty = lty, lwd = lwd, ..., identifier = identifier)
        panel.xyarea(smooth$x, smooth$y, ...)  ## Edited
    }
    smooth
}

不确定为什么@Josh,但是当我在我的机器上运行panel.filled_S函数时它不起作用 - 它不会绘制一个type="S"而是通常的type="p" - Geek On Acid
@GeekOnAcid,猜我复制了错误的代码。刚刚我重新复制到帖子中了,对我来说可以工作。那你呢? - Josh O'Brien
好的,现在可以正常工作了。你差不多分析了这些函数来让它工作,但它达到了目标 :) - Geek On Acid
1
实际上,对于一次性的操作,我只需执行 trace(panel.xyplot, edit=TRUE) 并直接在相关函数中插入单行代码 panel.xyarea(xx, yy, ...)。除此之外,任何比这更复杂的修改都是因为当我们定义一个新的面板函数时,我们已经将代码块从其余 panel.xyplot() 提供的变量环境中取出。对于更常规的使用,我可能会修改 panel.xyplot() 和相关函数,将它们命名为 panel.xyplot2() 等,并将它们打包到自己的包中,该包导入 latticelatticeExtra - Josh O'Brien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接