gpt4 book ai didi

r - 如何使用 annotation_custom() 在绘图区域的精确区域放置 grobs?

转载 作者:行者123 更新时间:2023-12-03 12:10:19 27 4
gpt4 key购买 nike

我正在尝试使用 ggplot2 重现以下 [base R] 图

enter image description here

我已经解决了大部分问题,但目前让我感到困惑的是将连接位于图右侧的边缘地毯图的线段放置在各自的标签上。标签是通过 anotation_custom() 绘制的(在下面的第二张图中),我使用了 @baptiste 关闭剪辑的技巧以允许在绘图边距中绘制。

尽管进行了多次尝试,我还是无法将 segmentGrobs() 放置在设备中的所需位置,以便它们连接正确的地毯刻度和标签。

一个可重现的例子是

y <- data.frame(matrix(runif(30*10), ncol = 10))
names(y) <- paste0("spp", 1:10)
treat <- gl(3, 10)
time <- factor(rep(1:10, 3))

require(vegan); require(grid); require(reshape2); require(ggplot2)
mod <- prc(y, treat, time)

如果您没有安装 vegan ,我会在问题的末尾附加一个强化对象的 dput 和一个 fortify() 方法(如果您希望运行示例和 fortify() 以便使用 ggplot() 进行方便的绘图)。我还包括一个有点冗长的函数 myPlt() ,它说明了我到目前为止所做的工作,如果您加载了包并且可以创建 mod ,则可以在示例数据集上使用它。

我已经尝试了很多选择,但我现在似乎在正确放置线段时在黑暗中挣扎。

我不是在寻找为示例数据集绘制标签/段的特定问题的解决方案,而是一个通用的解决方案,我可以用它来以编程方式放置段和标签,因为这将构成对象的 autoplot() 方法的基础 class(mod) 。我已经确定了标签,但不是线段。所以对于问题:
  • 当我想放置包含从数据坐标 xminxmaxyminymax 运行的行的段 grob 时,如何使用 x0y0x1y1 参数?
  • 也许换一种方式问,你如何使用 annotation_custom() 在 外绘制线段 已知数据坐标 x0y0x1y1 之间的绘图区域?

  • 我很乐意收到在绘图区域中只包含任何旧绘图的答案,但展示了如何在绘图边缘的已知坐标之间添加线段。

    我不喜欢使用 annotation_custom(),所以如果有更好的解决方案,我也会考虑。不过,我确实想避免在绘图区域中使用标签;我想我可以通过使用 annotate() 并通过 expand 参数扩展比例尺中的 x 轴限制来实现这一点。
    fortify() 方法
    fortify.prc <- function(model, data, scaling = 3, axis = 1,
    ...) {
    s <- summary(model, scaling = scaling, axis = axis)
    b <- t(coef(s))
    rs <- rownames(b)
    cs <- colnames(b)
    res <- melt(b)
    names(res) <- c("Time", "Treatment", "Response")
    n <- length(s$sp)
    sampLab <- paste(res$Treatment, res$Time, sep = "-")
    res <- rbind(res, cbind(Time = rep(NA, n),
    Treatment = rep(NA, n),
    Response = s$sp))
    res$Score <- factor(c(rep("Sample", prod(dim(b))),
    rep("Species", n)))
    res$Label <- c(sampLab, names(s$sp))
    res
    }
    dput()
    这是 fortify.prc(mod) 的输出:
    structure(list(Time = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 
    3, 4, 5, 6, 7, 8, 9, 10, NA, NA, NA, NA, NA, NA, NA, NA, NA,
    NA), Treatment = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Response = c(0.775222658013234,
    -0.0374860102875694, 0.100620532505619, 0.17475403767196, -0.736181209242918,
    1.18581913245908, -0.235457236665258, -0.494834646295896, -0.22096700738071,
    -0.00852429328460645, 0.102286976108412, -0.116035743892094,
    0.01054849999509, 0.429857364190398, -0.29619258318138, 0.394303081010858,
    -0.456401545475929, 0.391960511587087, -0.218177702859661, -0.174814586471715,
    0.424769871360028, -0.0771395073436865, 0.698662414019584, 0.695676522106077,
    -0.31659375422071, -0.584947748238806, -0.523065304477453, -0.19259357510277,
    -0.0786143714402391, -0.313283220381509), Score = structure(c(1L,
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Sample",
    "Species"), class = "factor"), Label = c("2-1", "2-2", "2-3",
    "2-4", "2-5", "2-6", "2-7", "2-8", "2-9", "2-10", "3-1", "3-2",
    "3-3", "3-4", "3-5", "3-6", "3-7", "3-8", "3-9", "3-10", "spp1",
    "spp2", "spp3", "spp4", "spp5", "spp6", "spp7", "spp8", "spp9",
    "spp10")), .Names = c("Time", "Treatment", "Response", "Score",
    "Label"), row.names = c("1", "2", "3", "4", "5", "6", "7", "8",
    "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
    "20", "spp1", "spp2", "spp3", "spp4", "spp5", "spp6", "spp7",
    "spp8", "spp9", "spp10"), class = "data.frame")

    我试过的:
    myPlt <- function(x, air = 1.1) {
    ## fortify PRC model
    fx <- fortify(x)
    ## samples and species scores
    sampScr <- fx[fx$Score == "Sample", ]
    sppScr <- fx[fx$Score != "Sample", ]
    ord <- order(sppScr$Response)
    sppScr <- sppScr[ord, ]
    ## base plot
    plt <- ggplot(data = sampScr,
    aes(x = Time, y = Response,
    colour = Treatment, group = Treatment),
    subset = Score == "Sample")
    plt <- plt + geom_line() + # add lines
    geom_rug(sides = "r", data = sppScr) ## add rug
    ## species labels
    sppLab <- sppScr[, "Label"]
    ## label grobs
    tg <- lapply(sppLab, textGrob, just = "left")
    ## label grob widths
    wd <- sapply(tg, function(x) convertWidth(grobWidth(x), "cm",
    valueOnly = TRUE))
    mwd <- max(wd) ## largest label

    ## add some space to the margin, move legend etc
    plt <- plt +
    theme(plot.margin = unit(c(0, mwd + 1, 0, 0), "cm"),
    legend.position = "top",
    legend.direction = "horizontal",
    legend.key.width = unit(0.1, "npc"))
    ## annotate locations
    ## - Xloc = new x coord for label
    ## - Xloc2 = location at edge of plot region where rug ticks met plot box
    Xloc <- max(fx$Time, na.rm = TRUE) +
    (2 * (0.04 * diff(range(fx$Time, na.rm = TRUE))))
    Xloc2 <- max(fx$Time, na.rm = TRUE) +
    (0.04 * diff(range(fx$Time, na.rm = TRUE)))
    ## Yloc - where to position the labels in y coordinates
    yran <- max(sampScr$Response, na.rm = TRUE) -
    min(sampScr$Response, na.rm = TRUE)
    ## This is taken from vegan:::linestack
    ## attempting to space the labels out in the y-axis direction
    ht <- 2 * (air * (sapply(sppLab,
    function(x) convertHeight(stringHeight(x),
    "npc", valueOnly = TRUE)) *
    yran))
    n <- length(sppLab)
    pos <- numeric(n)
    mid <- (n + 1) %/% 2
    pos[mid] <- sppScr$Response[mid]
    if (n > 1) {
    for (i in (mid + 1):n) {
    pos[i] <- max(sppScr$Response[i], pos[i - 1] + ht[i])
    }
    }
    if (n > 2) {
    for (i in (mid - 1):1) {
    pos[i] <- min(sppScr$Response[i], pos[i + 1] - ht[i])
    }
    }
    ## pos now contains the y-axis locations for the labels, spread out

    ## Loop over label and add textGrob and segmentsGrob for each one
    for (i in seq_along(wd)) {
    plt <- plt + annotation_custom(tg[[i]],
    xmin = Xloc,
    xmax = Xloc,
    ymin = pos[i],
    ymax = pos[i])
    seg <- segmentsGrob(Xloc2, pos[i], Xloc, pos[i])

    ## here is problem - what to use for ymin, ymax, xmin, xmax??
    plt <- plt + annotation_custom(seg,
    ## xmin = Xloc2,
    ## xmax = Xloc,
    ## ymin = pos[i],
    ## ymax = pos[i])
    xmin = Xloc2,
    xmax = Xloc,
    ymin = min(pos[i], sppScr$Response[i]),
    ymax = max(pos[i], sppScr$Response[i]))
    }
    ## Build the plot
    p2 <- ggplot_gtable(ggplot_build(plt))
    ## turn off clipping
    p2$layout$clip[p2$layout$name=="panel"] <- "off"
    ## draw plot
    grid.draw(p2)
    }

    图基于我在 myPlt() 中的尝试

    这是我使用上面的 myPlt() 所做的。请注意通过标签绘制的小水平刻度 - 这些应该是上面第一张图中的倾斜线段。

    enter image description here

    最佳答案

    也许这可以说明annotation_custom ,

    myGrob <- grobTree(rectGrob(gp=gpar(fill="red", alpha=0.5)),
    segmentsGrob(x0=0, x1=1, y0=0, y1=1, default.units="npc"))

    myGrob2 <- grobTree(rectGrob(gp=gpar(fill="blue", alpha=0.5)),
    segmentsGrob(x0=0, x1=1, y0=0, y1=1, default.units="npc"))

    p <- qplot(1:10, 1:10) + theme(plot.margin=unit(c(0, 3, 0, 0), "cm")) +
    annotation_custom(myGrob, xmin=5, xmax=6, ymin=3.5, ymax=5.5) +
    annotate("segment", x=5, xend=6, y=3, yend=5, colour="red") +
    annotation_custom(myGrob2, xmin=8, xmax=12, ymin=3.5, ymax=5.5)

    p

    g <- ggplotGrob(p)
    g$layout$clip[g$layout$name=="panel"] <- "off"
    grid.draw(g)

    enter image description here

    显然有一个奇怪的错误,如果我重用 myGrob而不是 myGrob2 ,它第二次忽略放置坐标并将其与第一层叠加。这个功能真的有问题。

    关于r - 如何使用 annotation_custom() 在绘图区域的精确区域放置 grobs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17492230/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com