以定义的方式排列图例中的项目。

huangapple go评论59阅读模式
英文:

Arrange items in a legend in a defined way

问题

我可以为您提供代码的翻译部分,以下是代码的翻译:

# 导入ggplot2库
library(ggplot2)

# 创建数据框DF
DF = data.frame(val = c(10,20,30,40,50,60,70,80,90,100), 
                param = rep(letters[1:5],2), 
                x = rep(c('X', 'Y'), 5))

# 使用ggplot创建图表
ggplot(data = DF) + 
  geom_bar(aes(y = val, fill = param, x = x), 
           stat = 'identity', 
           position = position_dodge2(preserve = 'single')) + 
  guides(fill = guide_legend(nrom = 2, byrow = TRUE))

另外,关于您在图例中看到的白色块问题,似乎与geom_col中的alpha = 0.6有关。您可以尝试将alpha值设置为1,或者在scale_fill_manual中设置颜色时考虑透明度。不过,具体如何解决问题可能需要进一步的调试和实验,因为涉及到颜色和透明度的调整。

请注意,我只提供了代码的翻译部分,不包括问题的回答。如果您需要更多帮助,请随时提出。

英文:

I have below ggplot

library(ggplot2)
DF = data.frame(val = c(10,20,30,40,50,60,70,80,90,100), param = rep(letters[1:5],2), x = rep(c('X', 'Y'), 5))
ggplot(data = DF) + geom_bar(aes(y = val, fill = param, x = x), stat = 'identity', position = position_dodge2(preserve = 'single')) + guides(fill = guide_legend(nrom = 2, byrow = TRUE))

While I can generate the plot, however, I want to arrange the items in the legend in a specific way as below.

  1. First 2 items i.e. a & b should be in the first row
  2. Remaining items should be arranged in an array fashion with 3 columns and applicable number of rows based on the number of items except first 2 i.e. a & b, starting from the second row (first row will only contain a & b)
  3. I also want to bold-face the items a & b only, in the legend

Is there any way to achieve such custom arrangement?

Based on the kind answer from @stefan, I modified my code as below

library(ggplot2)
library(scales)
library(dplyr)

DF = data.frame(val = c(10,20,30,40,50,60,70,80,90,100), param = rep(letters[1:5],2), x = rep(c('X', 'Y'), 5))

DF$param <- factor(DF$param, c("a", "b", "spacer", "c", "d", "e"))

pal_fill <- scales::hue_pal()(5)
names(pal_fill) <- letters[1:5]

pal_fill <- c(pal_fill, spacer = "transparent")

ggplot(data = DF) +
  geom_col(aes(y = val, fill = param, x = x), alpha = 0.6,
    position = position_dodge2(preserve = "single")
  ) +
  scale_fill_manual(
    values = pal_fill,
    drop = FALSE,
    labels = ~ dplyr::case_match(
      .x, "spacer" ~ "", c("a", "b") ~ paste0("**", .x, "**"),
      .default = .x)
  ) +
  guides(fill = guide_legend(
    nrow = 2, byrow = TRUE
  )) +
  theme(
    legend.position=c(.9,.75),
    legend.background = element_rect(fill = alpha('#e5e5e5', 0.60)),
    #legend.text = ggtext::element_markdown(),
    legend.key = element_rect(fill = "transparent")
  )

As you see, I see a white patch in the legend. This actually goes off if I remove alpha = 0.6 in geom_col. This is strange to me as I failed to understand the connection between alpha in geom_col and legend items.

Is there any way to correct this i.e. remove the white patch?

Any pointer will be very helpful.

答案1

得分: 2

如果我理解您的意思正确,那么实现您期望的结果的一种方法是为一些虚假的图例项添加一些虚假的图例键,通过删除标签并将填充颜色设置为例如 "transparent" 来使图例键“不可见”。

首先,这需要将 param 转换为因子,并在正确的位置添加虚假元素。此外,我们还必须为填充比例设置 drop=FALSE,以便未使用的虚假元素实际上在图例中显示出来。最后,仅加粗一些图例元素是最简单的任务,可以通过 ggtext::element_markdown 来实现。

注意:根据 theme 设置,将填充颜色设置为 "transparent" 不足以使虚假元素不可见,例如,默认的 theme_grey 在键上有灰色背景填充。因此,我添加了 legend.key = element_rect(fill = "transparent") 以使背景填充也透明。

library(ggplot2)
library(scales)
library(dplyr)

DF$param <- factor(DF$param, c("a", "b", "spacer", "c", "d", "e"))

pal_fill <- scales::hue_pal()(5)
names(pal_fill) <- letters[1:5]

pal_fill <- c(pal_fill, spacer = "transparent")

ggplot(data = DF) +
  geom_col(aes(y = val, fill = param, x = x),
    position = position_dodge2(preserve = "single")
  ) +
  scale_fill_manual(
    values = pal_fill,
    drop = FALSE,
    labels = ~ dplyr::case_match(
      .x, "spacer" ~ "", c("a", "b") ~ paste0("**", .x, "**"),
      .default = .x)
  ) +
  guides(fill = guide_legend(
    nrow = 2, byrow = TRUE
  )) +
  theme(
    legend.text = ggtext::element_markdown(),
    legend.key = element_rect(fill = "transparent")
  )

以定义的方式排列图例中的项目。

编辑 不得不承认我不太清楚问题在哪里,但解决方法是为“spacer”设置 alpha 为零,我在 geom_col 中使用 after_scaleif_else

ggplot(data = DF) +
  geom_col(
    aes(
      y = val, fill = param, x = x,
      alpha = after_scale(if_else(fill != "transparent", 0.6, 0))
    ),
    position = position_dodge2(preserve = "single")
  ) +
  scale_fill_manual(
    values = pal_fill,
    drop = FALSE,
    labels = ~ dplyr::case_match(
      .x, "spacer" ~ "", c("a", "b") ~ paste0("**", .x, "**"),
      .default = .x
    )
  ) +
  guides(fill = guide_legend(
    nrow = 2, byrow = TRUE
  )) +
  theme(
    legend.position = c(.9, .75),
    legend.background = element_rect(fill = alpha("#e5e5e5", 0.60)),
    #legend.text = ggtext::element_markdown(),
    legend.key = element_rect(fill = "transparent")
  )

以定义的方式排列图例中的项目。


<details>
<summary>英文:</summary>

If I understand you correctly then one approach to achieve your desired result would be to add some fake legend entries for which we make the legend keys &quot;invisible&quot; by removing the labels and setting the fill color to e.g. `&quot;transparent&quot;`. 

As a first step this requires to convert `param` to a factor and adding the fake elements at the correct position. Additionally we have to set `drop=FALSE` for the fill scale so that the unused fake elements are actually displayed in the legend. Finally, bolding only some of the legend elements is the easiest task and could be achieved via `ggtext::element_markdown`.

Note: Depending on the `theme` setting the fill color to `&quot;transparent&quot;` is not sufficient to make the fake elements invisible, e.g. in case of the default `theme_grey` the keys have a grey background fill. Hence, I added `legend.key = element_rect(fill = &quot;transparent&quot;)` to make the background fill transparent as well.

library(ggplot2)
library(scales)
library(dplyr)

DF$param <- factor(DF$param, c("a", "b", "spacer", "c", "d", "e"))

pal_fill <- scales::hue_pal()(5)
names(pal_fill) <- letters[1:5]

pal_fill <- c(pal_fill, spacer = "transparent")

ggplot(data = DF) +
geom_col(aes(y = val, fill = param, x = x),
position = position_dodge2(preserve = "single")
) +
scale_fill_manual(
values = pal_fill,
drop = FALSE,
labels = ~ dplyr::case_match(
.x, "spacer" ~ "", c("a", "b") ~ paste0("", .x, ""),
.default = .x)
) +
guides(fill = guide_legend(
nrow = 2, byrow = TRUE
)) +
theme(
legend.text = ggtext::element_markdown(),
legend.key = element_rect(fill = "transparent")
)


[![enter image description here][1]][1]


**EDIT** Have to admit that I don&#39;t know exactly what&#39;s the issue but a fix would be to set `alpha` for the &quot;spacer&quot; to zero for which I use `after_scale` and an `if_else` in `geom_col`:

ggplot(data = DF) +
geom_col(
aes(
y = val, fill = param, x = x,
alpha = after_scale(if_else(fill != "transparent", .6, 0))
),
position = position_dodge2(preserve = "single")
) +
scale_fill_manual(
values = pal_fill,
drop = FALSE,
labels = ~ dplyr::case_match(
.x, "spacer" ~ "", c("a", "b") ~ paste0("", .x, ""),
.default = .x
)
) +
guides(fill = guide_legend(
nrow = 2, byrow = TRUE
)) +
theme(
legend.position = c(.9, .75),
legend.background = element_rect(fill = alpha("#e5e5e5", 0.60)),
#legend.text = ggtext::element_markdown(),
legend.key = element_rect(fill = "transparent")
)


[![enter image description here][2]][2]


  [1]: https://i.stack.imgur.com/pO7cO.png
  [2]: https://i.stack.imgur.com/F4lms.png

</details>



huangapple
  • 本文由 发表于 2023年5月29日 14:20:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76355068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定