可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Probably an easy one.
I have an xy dataset I'd like to plot using R
's plotly
. Here are the data:
set.seed(1)
df <- data.frame(x=1:10,y=runif(10,1,10),group=c(rep("A",9),"B"),group.size=as.integer(runif(10,1,10)))
I'd like to color the data by df$group
and have the size of the points follow df$group.size
(i.e., a bubble plot). In addition, I'd like to have both legends added.
This is my naive attempt:
require(plotly)
require(dplyr)
main.plot <-
plot_ly(type='scatter',mode="markers",color=~df$group,x=~df$x,y=~df$y,size=~df$group.size,marker=list(sizeref=0.1,sizemode="area",opacity=0.5),data=df,showlegend=T) %>%
layout(title="Title",xaxis=list(title="X",zeroline=F),yaxis=list(title="Y",zeroline=F))
which comes out as:
and unfortunately messes up the legend, at least how I want it to be: a point for each group having the same size but different colors.
Then to add a legend for the group.size
I followed this, also helped by aocall's answer:
legend.plot <- plot_ly() %>% add_markers(x = 1, y = unique(df$group.size),
size = unique(df$group.size),
showlegend = T,
marker = list(sizeref=0.1,sizemode="area")) %>%
layout(title="TITLE",xaxis = list(zeroline=F,showline=F,showticklabels=F,showgrid=F),
yaxis=list(showgrid=F))
which comes out as:
Here my problem is that the legend is including values that do not exist in my data.
then I combine them using subplot
:
subplot(legend.plot, main.plot, widths = c(0.1, 0.9))
I get this:
where the legend title is eliminated
So I'd be helpful for some help.
回答1:
Based on the updated request:
Note the changes in legend.plot
(mapping values to a sequence of integers, then manually changing the axis tick text), and the use of annotations to get a legend title. As explained in this answer, only one title may be used, regardless of how many subplots are used.
The circle on the plot legend seems to correspond to the minimum point size of each trace. Thus, I've added a point at (12, 12), and restricted the range of the axes to ensure it isn't shown.
titleX
and titleY
control the display of axis labels, as explained here.
set.seed(1)
df <- data.frame(x=1:10,y=runif(10,1,10),group=c(rep("A",9),"B"),group.size=as.integer(runif(10,1,10)))
require(plotly)
require(dplyr)
## Take unique values before adding dummy value
unique_vals <- unique(df$group.size)
df <- rbind(c(12, 12, "B", 1), df)
df[c(1, 2, 4)] <- lapply(df[c(1, 2, 4)], as.numeric)
main.plot <-
plot_ly(type='scatter',
mode="markers",
color=~df$group,
x=~df$x,
y=~df$y,
size=~df$group.size,
marker=list(
sizeref=0.1,
sizemode="area",
opacity=0.5),
data=df,
showlegend=T) %>%
layout(title="Title",
xaxis=list(title="X",zeroline=F, range=c(0, 11)),
yaxis=list(title="Y",zeroline=F, range=c(0, 11)))
legend.plot <- plot_ly() %>%
add_markers(x = 1,
y = seq_len(length(unique_vals)),
size = sort(unique_vals),
showlegend = F,
marker = list(sizeref=0.1,sizemode="area")) %>%
layout(
annotations = list(
list(x = 0.2,
y = 1,
text = "LEGEND TITLE",
showarrow = F,
xref='paper',
yref='paper')),
xaxis = list(
zeroline=F,
showline=F,
showticklabels=F,
showgrid=F),
yaxis=list(
showgrid=F,
tickmode = "array",
tickvals = seq_len(length(unique_vals)),
ticktext = sort(unique_vals)))
subplot(legend.plot, main.plot, widths = c(0.1, 0.9),
titleX=TRUE, titleY=TRUE)
回答2:
Firstly, you are only passing in the unique values to the legend. If you pass in all possible values (ie, seq(min(x), max(x), by=1)
, or in this case seq_len(max(x))
) the legend will show the full range.
Secondly, sizeref
and sizemode
in the marker
argument alter the way that point size is calculated. The following example should produce a more consistent plot:
set.seed(1)
df <- data.frame(x=1:10,y=runif(10,1,10),group=c(rep("A",9),"B"),group.size=as.integer(runif(10,1,10)))
require(plotly)
require(dplyr)
a <- plot_ly(type='scatter',mode="markers",
color=~df$group,
x=~df$x,
y=~df$y,
size=df$group.size,
marker = list(sizeref=0.1, sizemode="area"),
data=df,
showlegend=F) %>%
layout(title="Title",
xaxis=list(title="X",zeroline=F),
yaxis=list(title="Y",zeroline=F))
b <- plot_ly() %>% add_markers(x = 1, y = seq_len(max(df$group.size)),
size = seq_len(max(df$group.size)),
showlegend = F,
marker = list(sizeref=0.1, sizemode="area")) %>%
layout(
xaxis = list(zeroline=F,showline=F,showticklabels=F,showgrid=F),
yaxis=list(showgrid=F))
subplot(b, a, widths = c(0.1, 0.9))