在 ggplotly 中,图例中的元素分组失败。

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

Grouping elements in legend fails with ggplotly

问题

在下面的示例中,分组的ggplot元素似乎可以正常工作,直到我使用plotly::ggplotly()转换绘图。我很难理解这是否是因为我做错了什么,还是这是另一个plotly的bug。

期望的输出:
正如您所看到的,ggplot中的图例被正确分组。

> plot

ggplotly(p = plot)将三个geom_segments中的两个添加到图例中。

为什么会发生这种情况,如何防止这种情况发生?
谢谢

在 ggplotly 中,图例中的元素分组失败。
在 ggplotly 中,图例中的元素分组失败。

编辑: 看起来与ggplotly中的组合geom_bar和geom_point图例有关。

英文:

In the following example, grouping ggplot-elements appears to work, until I convert the plot with plotly::ggplotly(). I'm struggling to understand if this is because I'm doing something wrong, or if this is another plotly-bug.

Reproducible Example

# example data
df <- structure(list(a = structure(list(est_score = c(0.208979731611907,0.328919041901827, 0.396166493743658), upper_bound = c(0.992965325427929,1.11290463571785, 1.18015208755968), lower_bound = c(-0.575005862204114,-0.455066551914195, -0.387819100072363), ci_range = c(1.56797118763204,1.56797118763204, 1.56797118763204)), row.names = c(NA, -3L), class = c("tbl_df","tbl", "data.frame")), b = structure(list(est_score = c(0.688612399809063,0.584376397356391, 0.63451482411474), upper_bound = c(1.47259799362508,1.36836199117241, 1.41850041793076), lower_bound = c(-0.0953731940069589,-0.19960919645963, -0.149470769701281), ci_range = c(1.56797118763204,1.56797118763204, 1.56797118763204)), row.names = c(NA, -3L), class = c("tbl_df","tbl", "data.frame")), c = structure(list(est_score = c(0.462245718948543,0.636445740051568, 0.206650576367974), upper_bound = c(1.24623131276456,1.42043133386759, 0.990636170183996), lower_bound = c(-0.321739874867478,-0.147539853764454, -0.577335017448047), ci_range = c(1.56797118763204,1.56797118763204, 1.56797118763204)), row.names = c(NA, -3L), class = c("tbl_df","tbl", "data.frame")), d = structure(list(est_score = c(0.105384588986635,0.456747563555837, 0.281916436739266), upper_bound = c(0.889370182802657,1.24073315737186, 1.06590203055529), lower_bound = c(-0.678601004829386,-0.327238030260185, -0.502069157076755), ci_range = c(1.56797118763204,1.56797118763204, 1.56797118763204)), row.names = c(NA, -3L), class = c("tbl_df","tbl", "data.frame"))), row.names = c(NA, -3L), class = c("tbl_df","tbl", "data.frame"))
library(dplyr)
library(tidyr)
library(ggplot2)
library(plotly)

y_names <- colnames(df) %>% unique()
y_n <- length(y_names)

plot_data <- df %>% mutate("case_id" = row_number()) %>% 
  tidyr::pivot_longer(
    cols = -case_id
  ) %>%
  arrange(name)


plot <- ggplot()

plot <- plot + geom_point(
  data = plot_data,
  aes(
    x = value$est_score,
    y = factor(name),
    shape = factor(case_id),
    color = factor(case_id)
  ),
  size = 2
)

plot <- plot + ggplot2::geom_segment(
  data = plot_data,
  aes(
    y = factor(name),
    yend = factor(name),
    x = value$lower_bound,
    xend = value$upper_bound,
    color = factor(case_id)
  ),
  size = .2
)

Desired output

As you can see, the legend in ggplot is grouped correctly

> plot

While ggplotly(p = plot) adds two of the three geom_segments to the legend.

Why does this happen and how to prevent this?
Thanks

在 ggplotly 中,图例中的元素分组失败。
在 ggplotly 中,图例中的元素分组失败。

EDIT: Appears to be related to Combined geom_bar and geom_point legend in ggplotly

答案1

得分: 1

我查看了转换后的plotly对象,并找到了一个临时(但不太好看的)解决方案:

pp <- ggplotly(
  p = plot
)

当检查pp$x$data时,可以看出namelegendgroupshowlegend在某些geoms中设置不同。可以通过手动循环遍历转换后的对象来修复这个问题:

n_cases <- length(unique(plot_data$case_id))
for (i in 1:n_cases) {
  pp$x$data[[i]]$name <- i
  pp$x$data[[i]]$legendgroup <- i
  pp$x$data[[i + n_cases]]$name <- i
  pp$x$data[[i + n_cases]]$legendgroup <- i
  pp$x$data[[i + n_cases]]$showlegend <- FALSE
}

这可能是plotly的一个bug,但由于没有其他选择,我将继续使用这个解决方案。

英文:

I took a look at the converted plotly-object and figured out a temporary (but ugly) fix:

pp &lt;- ggplotly(
  p = plot
)

When examining pp$x$data, it becomes apparent that name, legendgroup and showlegend are set differently for some of the geoms. This can be fixed manually, e.g. by looping through the converted object:

n_cases &lt;- length(unique(plot_data$case_id))
for (i in 1:n_cases) {
  pp$x$data[[i]]$name &lt;- i
  pp$x$data[[i]]$legendgroup &lt;- i
  pp$x$data[[i + n_cases]]$name &lt;- i
  pp$x$data[[i + n_cases]]$legendgroup &lt;- i
  pp$x$data[[i + n_cases]]$showlegend &lt;- FALSE
}

This is probably a bug in plotly, but for the lack of alternatives, I will stick to this solution.

huangapple
  • 本文由 发表于 2020年1月6日 22:25:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/59613787.html
匿名

发表评论

匿名网友

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

确定