我有一个 R Plotly 子图,但存在跟踪图例重复的问题:
这是一个常见问题:
- Looping through R Plotly with subplot and hiding all legend except one
- How to remove duplicate legend entries w/ plotly subplots()
- Plotly subplots with shared legend in R
- Merging legends in plotly subplot
- Removing Unused Subplot in R Plotly
- Display all levels in plotly subplot legend without duplicates
其中一些有(不)相关的答案,有些则没有。
本质上,解决方案是强制第一个子图显示图例,并为所有其他子图禁用它。然而,执行此操作的方法取决于实现,即子图是使用列表还是函数生成。 就我而言,我使用的函数使得强制一个子图显示图例而不显示其他子图变得很棘手。
最小工作示例:
# clear env
rm(list = ls())
# libraries
library(plotly)
library(reshape2)
# prepare dataset
attach(mtcars)
mtcars$car <- rownames(mtcars)
mtcars <- melt(mtcars)
# generate plot of variable
pl <- . %>%
plot_ly(
x = ~car,
y = ~value,
type = 'scatter',
mode = 'markers',
color = I('blue'),
name = 'value',
legendgroup = 'batches',
showlegend = TRUE
) %>%
layout(
xaxis = list(
type = 'category'
),
yaxis = list(
title = ~unique(variable)
)
)
# generate subplot view
mtcars %>%
group_by(variable) %>%
do(
p = pl(.)
) %>%
subplot(
nrows = NROW(.),
shareX = TRUE,
titleY = TRUE
)
这会生成上面的图像。
在我的尝试中,我一直尝试使用带有全局变量的闭包,该变量在第一个子图之后设置为 FALSE,但它没有按预期工作。尽管在控制台中看到它正确设置了全局变量,但所有图例条目都消失了。
# set global showlegend variable
# we will set to FALSE after first plot
showlegend <- TRUE
# generate plot of variable
pl <- . %>%
plot_ly(
x = ~car,
y = ~value,
type = 'scatter',
mode = 'markers',
color = I('blue'),
name = 'value',
legendgroup = 'batches',
# use a closure to set showlegend
showlegend = (function(){
# echo to console
print(showlegend)
if(showlegend){
# at first plot this will run
# set to FALSE for subsequent plots
showlegend <<- FALSE
return(TRUE)
} else {
# runs for all except first
return(FALSE)
}
})()
) %>%
layout(
xaxis = list(
type = 'category'
),
yaxis = list(
title = ~unique(variable)
)
)
控制台输出:TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
基于此,我希望有一个图例条目,但图表显示没有图例条目。为什么这没有按预期工作?
是否有一种更有效的方法可以在没有闭包和全局变量的情况下切换 showlegend 变量?
最佳答案
在进一步思考这个问题之后,我意识到 Plotly 可能会删除单个图例条目,即当绘制多个带有图例的迹线时,仅显示图例。
事实上,当添加额外的跟踪时,图表会按预期显示图例。
解决方案:
# set global showlegend variable
# we will set to FALSE after first plot
showlegend <- TRUE
# generate plot of variable
pl <- . %>%
plot_ly(
x = ~car,
y = ~value,
type = 'scatter',
mode = 'markers',
color = I('blue'),
name = 'value',
legendgroup = 'batches',
showlegend = showlegend
) %>%
add_trace(
y = ~value,
name = 'target',
type='scatter',
mode = 'lines',
line=list(
color='black',
dash='dash'
),
showlegend = (function(){
if(showlegend){
showlegend <<- FALSE
return(TRUE)
} else {
return(FALSE)
}
})()
) %>%
layout(
xaxis = list(
type = 'category'
),
yaxis = list(
title = ~unique(variable)
)
)
请注意,闭包必须应用于最后绘制的迹线,否则全局变量设置为 FALSE 太早。
更新:在测试过程中,我发现以下方法也有效:
showlegend = (~unique(variable) == "mpg")
或者如果您不想对变量比较进行硬编码:
showlegend = (~unique(variable) == unique(mtcars$variable)[1])
这是我现在比全局变量闭包更喜欢的方法
关于删除 R 绘图子图中的图例重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64536038/