为什么Geom_Rect颜色仅facet_wrap的第一行?

发布于 2025-02-13 06:08:27 字数 1406 浏览 1 评论 0 原文

我试图在我的 facet_wrap 绘图的每个偶数面板上获得阴影矩形。但是,当我使用 geom_Rect 时,它仅在第二个面板上产生矩形。我尝试使用 Annotate geom_tile ,但没有成功。我认为我在这里缺少一些简单的细节,这可能与我的X变量是分类而不是数字有关的事实,但是我已经在几个小时进行了战斗...

这是我的代码:

even_numbers <- seq(2,nrow(df.plt),2)
ggplot(df.plt) + 
  geom_rect(data = df.plt[even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

以及由此产生的图: 带有geom_rect和facet_wrap无法按预期工作的

绘图

结果 复制我的问题:

set.seed(002) # just to make it reproducible
df.tmp = data.frame(nst = rnorm(100*2), Srs = sample(rep(c("S3","S4"),100)), Cnd = sample(rep(c("DN","DA","DV","DAV"),50)), Grp = sample(rep(c("close","far"),100)))

even_numbers <- seq(2,nrow(df.tmp),2)
ggplot(df.tmp) + 
  geom_rect(data = df.tmp[even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

I am trying to get shaded rectangles on every even-numbered panel of my facet_wrap plot. However, when I use geom_rect, it produces the rectangles only on the second panel. I tried using annotate and geom_tile but with no success. I presume I am missing some simple detail here, probably related to the fact that my X variable is categorical and not numeric, but I am fighting this for a few hours already...

Here is my code:

even_numbers <- seq(2,nrow(df.plt),2)
ggplot(df.plt) + 
  geom_rect(data = df.plt[even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

And the resulting plot:
resulting plot with geom_rect and facet_wrap not working as expected

Edit:

I have created a dummy dataset example which replicates my issue:

set.seed(002) # just to make it reproducible
df.tmp = data.frame(nst = rnorm(100*2), Srs = sample(rep(c("S3","S4"),100)), Cnd = sample(rep(c("DN","DA","DV","DAV"),50)), Grp = sample(rep(c("close","far"),100)))

even_numbers <- seq(2,nrow(df.tmp),2)
ggplot(df.tmp) + 
  geom_rect(data = df.tmp[even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

皇甫轩 2025-02-20 06:08:28

尽管您的想法是正确的恕我直言,但您可以通过将 Xmin Xmax 值放在数据框架中并通过审美绘制美观来更轻松地实现所需的结果。首先要注意,我们只需要一个均匀数的长度的向量(unique(df.tmp $ cnd)),即 cnd 的类别数。其次,当我们混合离散和连续的X变量时,我在 GEOM_RECT 之前添加了 scale_x_discrete ,否则我们会遇到错误。

library(ggplot2)

even_numbers <- seq(2, length(unique(df.tmp$Cnd)), 2)

rects <- data.frame(
  xmin = even_numbers - 0.5,
  xmax = even_numbers + 0.5
)

ggplot(df.tmp) +
  scale_x_discrete() +
  geom_rect(
    data = rects, aes(xmin = xmin, xmax = xmax),
    ymin = -Inf, ymax = Inf, alpha = 0.3, fill = "grey"
  ) +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) +
  facet_wrap(vars(Grp), ncol = 1)

“”

edit 以防万一。您的方法不起作用的原因是,用于RECT的数据的相关部分仅包含 far 组。问题是,基本上仅显示与范围1到4( cnd 类别的数量)中对应的均匀数字。从以下代码段中可以看出,该代码段复制了用于方法中的Rects下的数据下的数据,仅存在 far grp(在过滤范围1至4的均匀数字之后):

even_numbers <- seq(2,nrow(df.tmp),2)

dplyr::bind_cols(df.tmp[even_numbers, ], data.frame(even_number = even_numbers)) |> 
  dplyr::filter(even_number <= 4)
#>          nst Srs Cnd Grp even_number
#> 1  0.1848492  S3  DV far           2
#> 2 -1.1303757  S3  DA far           4

While your idea was right IMHO you could achieve your desired result more easily by putting the xmin and xmax values in a dataframe and by mapping on aesthetics. First note that we only need a vector of even numbers of length(unique(df.tmp$Cnd)), i.e. the number of categories of Cnd. Second, as we are mixing discrete and continuous x variables I added an scale_x_discrete before geom_rect as otherwise we will get an error.

library(ggplot2)

even_numbers <- seq(2, length(unique(df.tmp$Cnd)), 2)

rects <- data.frame(
  xmin = even_numbers - 0.5,
  xmax = even_numbers + 0.5
)

ggplot(df.tmp) +
  scale_x_discrete() +
  geom_rect(
    data = rects, aes(xmin = xmin, xmax = xmax),
    ymin = -Inf, ymax = Inf, alpha = 0.3, fill = "grey"
  ) +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) +
  facet_wrap(vars(Grp), ncol = 1)

EDIT Just in case. The reason why your approach did not work is that the relevant part of the data used for the rects contains only the far group. The issue is that basically only rects corresponding to even numbers in the range 1 to 4 (the number of Cnd categories) are displayed. As can be seen from the following code snippet which replicates the data which under the hood is used for the rects in your approach only the far grp is present (after filtering for even numbers in the range 1 to 4):

even_numbers <- seq(2,nrow(df.tmp),2)

dplyr::bind_cols(df.tmp[even_numbers, ], data.frame(even_number = even_numbers)) |> 
  dplyr::filter(even_number <= 4)
#>          nst Srs Cnd Grp even_number
#> 1  0.1848492  S3  DV far           2
#> 2 -1.1303757  S3  DA far           4
情未る 2025-02-20 06:08:28

我一直在尝试了解为什么只有第二部分被阴影。最终,我准备了第二个示例,其中我找到了另一个可能的解决方案。但是,我不完全满意,因为我不了解 geom_Rect / facet_wrap ;我只找到了一些解决方法。

这是一个示例:

# constructing the dataframe so all the combinations are present for both even and odd rows
df.tmp = data.frame(nst = rnorm(16*6), 
                    Srs = rep(c("S3", "S4"), each=8, 6), 
                    Cnd = rep(c("DN", "DA", "DV", "DAV"), each=2, 12), 
                    Grp = rep(c(rep(c("close","far"), 8), rev(rep(c("close","far"), 8))),3) )

even_numbers <- seq(2,nrow(df.tmp),2) # so the df.tmp[even_numbers, ] contains all the combinations
ggplot(df.tmp) + 
  geom_rect(data = df.tmp[even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

正如您在此处看到的那样,尽管确保 df.tmp [vest_numbers,] Incluber CLOSE> CLOSE datapoints,但该图仅在第二行中阴影矩形。 : “第一行中的非阴影段”

在这里我更改 ggplot ,因此它包含 geom_Rect 分别用于关闭 far segments:

even_numbers <- seq(2,length(unique(df.tmp$Cnd)),2) # here the df.tmp[even_numbers, ] doesn't need to have all the combinations
ggplot(df.tmp) + 
  geom_rect(data = df.tmp[df.tmp$Grp=="close", ][even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') + 
  geom_rect(data = df.tmp[df.tmp$Grp=="far", ][even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

如下所示,它现在有效:

正如我之前提到的,我仍然不确定为什么 geom_rect 在第一个 地方。在我的解决方案中,需要为每个段准备一个单独的 geom_Rect ,因此绝对不是其中许多图的解决方案。我试图找到一种更优雅的方式,因此不必打扰宣布多少个部分或其他分组。

I have been trying to understand why only the second segment gets shaded. Eventually I prepared a second example, in which I have found another possible solution. However, I am not fully satisfied as I did not understand the issue with geom_rect / facet_wrap; I only found some workaround.

Here's the example:

# constructing the dataframe so all the combinations are present for both even and odd rows
df.tmp = data.frame(nst = rnorm(16*6), 
                    Srs = rep(c("S3", "S4"), each=8, 6), 
                    Cnd = rep(c("DN", "DA", "DV", "DAV"), each=2, 12), 
                    Grp = rep(c(rep(c("close","far"), 8), rev(rep(c("close","far"), 8))),3) )

even_numbers <- seq(2,nrow(df.tmp),2) # so the df.tmp[even_numbers, ] contains all the combinations
ggplot(df.tmp) + 
  geom_rect(data = df.tmp[even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

As you can see here, the plot has shaded rectangles only in the second row, despite ensuring the df.tmp[even_numbers, ] includes close datapoints as well: non-shaded segments in first line

Here I change the ggplot so it contains geom_rect separately for close and far segments:

even_numbers <- seq(2,length(unique(df.tmp$Cnd)),2) # here the df.tmp[even_numbers, ] doesn't need to have all the combinations
ggplot(df.tmp) + 
  geom_rect(data = df.tmp[df.tmp$Grp=="close", ][even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') + 
  geom_rect(data = df.tmp[df.tmp$Grp=="far", ][even_numbers, ],
            xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
            ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
  geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) + 
  facet_wrap(vars(Grp), ncol=1)

As you can see below, it works now: enter image description here

As I mentioned earlier, I am still not sure why geom_rect did not work in the first place. In my solution, a separate geom_rect needs to be prepared for each segment, so it's definitely not a solution for a plot with many of them. I was trying to find a more elegant way, so one wouldn't have to bother how many segments or other groupings are declared.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文