如何在使用Plotly创建的分组柱状图上对齐散点图轨迹。

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

How to align a scatter trace on grouped bar chart with plotly

问题

我对r plotly相当新,并创建了一个柱状图,显示了残疾人按年份分组的收入来源。现在我正在尝试添加一个散点轨迹,以显示非残疾人的标记比较,但是标记没有正确对齐,它们在x轴类别上居中对齐,而不是按年份变量分组,就像柱状图一样。通过谷歌搜索,我发现在GitHub上有人遇到了相同的问题,但没有看到解决方案。是否有一种简单的方法可以使散点轨迹的标记按年份变量对齐,以便它们与柱状图对齐?

我需要在HTML报告中为7个图表生成这个图表。

这是我的当前代码块:

library(plotly)
Figure16 <- pivot_longer(Figure16, cols=c('Wages and salaries','All Pensions','All Social Security benefits','Self employment income'), names_to='Sources', values_to='Rate')
Figure16$`Rate` <- as.numeric(as.character(Figure16$`Rate`)) * 100

#wrapping labels on chart
Figure16$wrappedy <- sapply(Figure16$Sources,
FUN = function(Sources) {paste(strwrap(Sources, width = 25), collapse = "<br>")})

Figure_16 <- plot_ly(Figure16[Figure16$Disability =="Disabled",],
                  x = ~wrappedy,
                y = ~Rate,
                type = 'bar',
                color = ~Year,
                colors = c("#8FAADC","#2F5597","#203864"),
                name = ~Year,
                #change colours depending on grouping
                marker = list(color = ifelse(Figure16$Year=="2017/18","#8FAADC",
                                       ifelse(Figure16$Year=="2018/19","#2F5597",
                                        ifelse(Figure16$Year=="2019/20","#203864",
                                               ""))),
                              pattern = list(shape = ifelse(Figure16$Year=="2017/18","x",
                                       ifelse(Figure16$Year=="2018/19","/",
                                         ""))),
                              line = list(color = ifelse(Figure16$Year=="2017/18","#8FAADC",
                                       ifelse(Figure16$Year=="2018/19","#2F5597",
                                        ifelse(Figure16$Year=="2019/20","#203864",
                                               ""))), width = 1.25))
                           )%>%
  #adding line markers for comparison group
     add_trace(Figure16[Figure16$Disability =="Non-disabled",], x = ~wrappedy, y = ~Rate, type = 'scatter',  mode = 'markers', name = 'Non-disabled', marker = list(size = 30, symbol ='line-ew-open', color = "#FFC000",line=list(color = "#FFC000"), width = 33))%>%
  #Making the yaxis start at zero and placing vertical line on chart
  layout(yaxis = list(rangemode='tozero',ticksuffix = "%"))

  #remove modebar as it overlaps with title
config(Figure_16, displayModeBar = FALSE)%>% layout(
  xaxis = list(title = ""),
  yaxis = list(title = "")
) %>%
  #Making the xaxis start at zero
  layout(yaxis = list(rangemode='tozero'))

希望这可以帮助你解决问题。

英文:

I'm quite new to r plotly and have created a bar chart showing income sources grouped by year for disabled people. Now I'm trying to add a scatter trace to show the comparison with markers for non-disabled people, but the markers aren't aligning properly, they align centrally on the x-axis category rather than grouping by the year variable like the bars. From googling, I found someone else had the same issue on github, but didn't see a solution. Is there a simple way to make the markers for the scatter trace align by the year variable so they align with the bars?

I need to produce this for 7 charts in an html report, so would appreciate some help.

My data for this chart:

structure(list(Disability = c(&quot;Disabled&quot;, &quot;Disabled&quot;, &quot;Disabled&quot;
), Year = c(&quot;2017/18&quot;, &quot;2018/19&quot;, &quot;2019/20&quot;), `Wages and salaries` = c(0.32, 
0.34, 0.37), `All Pensions` = c(0.34, 0.32, 0.31), `All Social Security benefits` = c(0.37, 
0.27, 0.23), `Self employment income` = c(0.03, 0.03, 0.06)), class = c(&quot;tbl_df&quot;, 
&quot;tbl&quot;, &quot;data.frame&quot;), row.names = c(NA, -3L))

Here is my current code chunk.

library(plotly)
Figure16 &lt;- pivot_longer(Figure16, cols=c(&#39;Wages and salaries&#39;,&#39;All Pensions&#39;,&#39;All Social Security benefits&#39;,&#39;Self employment income&#39;), names_to=&#39;Sources&#39;, values_to=&#39;Rate&#39;)
Figure16$`Rate` &lt;- as.numeric(as.character(Figure16$`Rate`)) * 100
#wrapping labels on chart
Figure16$wrappedy &lt;- sapply(Figure16$Sources,
FUN = function(Sources) {paste(strwrap(Sources, width = 25), collapse = &quot; &lt;br&gt; &quot;)})
Figure_16 &lt;- plot_ly(Figure16[Figure16$Disability ==&quot;Disabled&quot;,],
x = ~wrappedy,
y = ~Rate,
type = &#39;bar&#39;,
color = ~Year,
colors = c(&quot;#8FAADC&quot;,&quot;#2F5597&quot;,&quot;#203864&quot;),
name = ~Year,
#change colours depending on grouping
marker = list(color = ifelse(Figure16$Year==&quot;2017/18&quot;,&quot;#8FAADC&quot;,
ifelse(Figure16$Year==&quot;2018/19&quot;,&quot;#2F5597&quot;,
ifelse(Figure16$Year==&quot;2019/20&quot;,&quot;#203864&quot;,
&quot;&quot;))),
pattern = list(shape = ifelse(Figure16$Year==&quot;2017/18&quot;,&quot;x&quot;,
ifelse(Figure16$Year==&quot;2018/19&quot;,&quot;/&quot;,
&quot;&quot;))),
line = list(color = ifelse(Figure16$Year==&quot;2017/18&quot;,&quot;#8FAADC&quot;,
ifelse(Figure16$Year==&quot;2018/19&quot;,&quot;#2F5597&quot;,
ifelse(Figure16$Year==&quot;2019/20&quot;,&quot;#203864&quot;,
&quot;&quot;))), width = 1.25))
)%&gt;%
#adding line markers for comparison group
add_trace(Figure16[Figure16$Disability ==&quot;Non-disabled&quot;,], x = ~wrappedy, y = ~Rate, type = &#39;scatter&#39;,  mode = &#39;markers&#39;, name = &#39;Non-disabled&#39;, marker = list(size = 30, symbol =&#39;line-ew-open&#39;, color = &quot;#FFC000&quot;,line=list(color = &quot;#FFC000&quot;), width = 33))%&gt;%
#Making the yaxis start at zero and placing vertical line on chart
layout(yaxis = list(rangemode=&#39;tozero&#39;,ticksuffix = &quot;%&quot;))
#remove modebar as it overlaps with title
config(Figure_16, displayModeBar = FALSE)%&gt;% layout(
xaxis = list(title = &quot;&quot;),
yaxis = list(title = &quot;&quot;)
) %&gt;%
#Making the xaxis start at zero
layout(yaxis = list(rangemode=&#39;tozero&#39;))

答案1

得分: 1

我找到了一个解决方法,Plotly团队在Python中提出了一个解决方案(你可以在这里阅读)。以下是一个稍微变化的方法,可以帮助你达到你想要的效果。

我编写的条形追踪代码看起来有很大不同,但实际上与你的代码执行的是相同的操作。

我创建了一个名为 cols 的对象,其中包含了颜色的命名向量。这是为了让第二个追踪不会导致Plotly推断应该对第一个追踪进行更改。

第二个追踪,创建线条的那个,实际上是一个修改过的箱线图。因为每个组只有一个值,所以它只是一条线。由于它是一个箱线图,你可以像对待条形图一样对其进行分组和间隙处理。

layout 中,我设置了 boxmode 以及组内和组间的间隙。

                                  # 命名的颜色向量
cols <- setNames(c("#8FAADC","#2F5597","#203864"), paste0("201", 7:9, "/", 18:20))

                                  # 原始的条形图
plot_ly(Figure16[Figure16$Disability =="Disabled",], x = ~wrappedy, y = ~Rate,
        type = 'bar', color = ~Year, name = ~Year, colors = cols, # <<--- 颜色向量
        marker = list(pattern = list(shape = rep(c("x", "/", ""), each = 4)),
                      line = list(width = 1.5))) %>%
                                  # 修改后的箱线图以放置线条
  add_trace(Figure16[Figure16$Disability =="Non-disabled",], x = ~wrappedy, y = ~Rate,
            color = ~as.factor(Year), name = 'Non-disabled', type = "box", 
            line = list(color = "FFC000"), fillcolor = "white") %>%
                                  # 布局以对齐条形和箱线追踪
  layout(boxmode = "group", bargroupgap = 0, boxgroupgap = 0, 
         boxgap = .2, bargap = .2, 
         yaxis = list(rangemode='tozero', ticksuffix = "%", title = ""),
         xaxis = list(title = "")) %>%
  config(displayModeBar = F)

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


[1]: https://i.stack.imgur.com/A5tQJ.png
<details>
<summary>英文:</summary>
I found a workaround that the Plotly team in Python came up with ([you can read about that here](https://github.com/plotly/plotly.js/issues/4913)). Here&#39;s a variation of that to get you what you&#39;re looking for.
The bar trace code that I&#39;ve written looks a lot different, but it&#39;s doing the exact same thing as in your code.
I&#39;ve created an object, `cols`, that contains your colors in a named vector. This is so that the second trace does not cause Plotly to infer that changes should occur to the first trace.
The second trace, the one that creates the lines is actually a modified *box plot*. Since there is only one value per group, it&#39;s just a line. Since it&#39;s a box plot, you can group and gap it like a bar chart.
In `layout`, I&#39;ve set the `boxmode`, and the gaps between and within groups.
                              # named color vector

cols <- setNames(c("#8FAADC","#2F5597","#203864"), paste0("201", 7:9, "/", 18:20))

                              # original bar chart 

plot_ly(Figure16[Figure16$Disability =="Disabled",], x = ~wrappedy, y = ~Rate,
type = 'bar', color = ~Year, name = ~Year, colors = cols, # <<--- color vector
marker = list(pattern = list(shape = rep(c("x", "/", ""), each = 4)),
line = list(width = 1.5))) %>%
# modified box plot for line placement
add_trace(Figure16[Figure16$Disability =="Non-disabled",], x = ~wrappedy, y = ~Rate,
color = ~as.factor(Year), name = 'Non-disabled', type = "box",
line = list(color = "FFC000"), fillcolor = "white") %>%
# layout to align bar and box traces
layout(boxmode = "group", bargroupgap = 0, boxgroupgap = 0,
boxgap = .2, bargap = .2,
yaxis = list(rangemode='tozero', ticksuffix = "%", title = ""),
xaxis = list(title = "")) %>%
config(displayModeBar = F)


[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/A5tQJ.png
</details>

huangapple
  • 本文由 发表于 2023年7月31日 22:56:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76804831.html
匿名

发表评论

匿名网友

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

确定