可能很简单。
我有想要绘制的数据点(带有误差线)。 分组因素有两个级别:
group
和 cluster
:
set.seed(1)
df <- data.frame(cluster=rep(LETTERS[1:10],2),group=c(rep("A",10),rep("B",10)),point=rnorm(20),err=runif(20,0.1,0.3))
df$group <- factor(df$group,levels=c("A","B"))
我想绘制
x-axis
为 df$cluster
的点,并且在每个 cluster
内,这些点由 df$group
进行颜色编码并分割(以便 group
A
点保留为 group
B
点)。
这就是我正在尝试的:
library(plotly)
plot_ly(x=~df$cluster,y=~df$point,split=~df$group,type='scatter',mode="markers",showlegend=T,color=~df$group) %>%
layout(legend=list(orientation="h",xanchor="center",x=0.5,y=1),xaxis=list(title=NA,zeroline=F,categoryorder="array",categoryarray=sort(unique(df$cluster)),showticklabels=T),yaxis=list(title="Val",zeroline=F)) %>%
plotly::add_trace(error_y=list(array=df$err),showlegend=F)
非常接近,但唯一不起作用的是将每个
cluster
中的点按 group
分开。
知道如何让它发挥作用吗?理想情况下,代码应该是通用的,以便在每个
cluster
内分割任意数量的组级别,而不是特定于本示例的 A
和 B
的代码。
我喜欢
plotly
并且几乎只使用它,但是 ggplot2
内置了一些不错的功能,需要进行一些调整才能在 plotly
中复制。
不过,我认为如果您计划发布交互式图供其他人审阅,那么真正了解一些更详细的细节是值得的。如果您使用本机语法而不是
R
,ggplotly
API 提供了大量可用于调整的控制,并使每个小细节都变得完美。
话虽如此,我将如何解决这个问题:
(有问题提供数据生成代码)
library(plotly)
set.seed(1)
df <- data.frame(cluster=rep(LETTERS[1:10],2),
group=c(rep("A",10),
rep("B",10)),
point=rnorm(20),
err=runif(20,0.1,0.3))
df$group <- factor(df$group,levels=c("A","B"))
首先,你需要系统地自己做一些手动“抖动”。我还没有阅读在
ggplot2
函数中“自动神奇地”执行此操作的等效源代码,但我想象类似的事情正在幕后发生。
## Generate a set of offsets based on the number of group
Offset <- data.frame(group = unique(df$group),
offset = seq(-0.1, 0.1,length.out = length(unique(df$group))))
## Join the offset to the data frame based on group
df <- merge(df,Offset,by = "group", all.x = TRUE)
## Calculate an x location
df$x_location <- as.numeric(as.factor(df$cluster)) + df$offset
head(df)
后期处理:
group cluster point err offset x_location
1 A A -0.6264538 0.2641893 -0.1 0.9
2 A B 0.1836433 0.2294120 -0.1 1.9
3 A C -0.8356286 0.2565866 -0.1 2.9
4 A D 1.5952808 0.2106073 -0.1 3.9
5 A E 0.3295078 0.2059439 -0.1 4.9
6 A F -0.8204684 0.2578712 -0.1 5.9
现在您有了明确的 x_location,您可以在散点图上使用它,然后使用数组添加分类刻度线/文本。然后,通过在
text
中显示感兴趣的值,您可以从 x
中消除 y
和 hoverinfo
值,以完全覆盖您的踪迹。
df %>%
plot_ly() %>%
add_trace(x= ~x_location,y= ~point, color= ~group,
text = ~paste0("Group ",group," - Cluster ", cluster,"<br>",round(point,2)),
error_y = list(type = "data", array = ~err),
hoverinfo = "text",
type = "scatter", mode = "markers") %>%
layout(hovermode = "compare",
paper_bgcolor = 'rgba(235,235,235,0)',
plot_bgcolor = "rgba(235,235,235,1)",
legend=list(orientation="h",
xanchor="center",
yanchor = "bottom",
x=0.5,y=1,
bgcolor = "transparent"),
xaxis=list(title=NA,
zeroline=FALSE,
tickmode = "array",
tickvals = unique(as.numeric(sort(as.factor(df$cluster)))),
ticktext = unique(sort(as.factor(df$cluster))),
gridcolor = "rgba(255,255,255,1)"),
yaxis=list(title="Val",
zeroline=FALSE,
gridcolor = "rgba(255,255,255,1)"))
我不太熟悉
plotly
包。我不确定这是否符合您的要求。
但这里有一个使用
unite
包中的 tidyr
的解决方法。在与 plotly
一起使用之前创建了 cluster-group 对。
library(tidyr)
df1 <- df %>% unite(c('cluster','group'), col = 'clust_grp', sep = "-", remove = F)
plot_ly(df1, x=~clust_grp, y=~point, type='scatter', mode="markers", showlegend=T, color=~group) %>%
layout(legend=list(orientation="h",xanchor="center",x=0.5,y=1),xaxis=list(title="cluster_group",
zeroline=F, categoryorder="array", categoryarray = sort(unique(df1$clust_grp)), showticklabels=T), yaxis=list(title="Val", zeroline=F)) %>%
plotly::add_trace(error_y=list(array=df1$err), showlegend=F)