用 R 中的线条连接条形图

Connect bars with lines in R plotly

我正在尝试用线条连接堆叠的条形图。

期望:

但是我无法在条形图之间画出线条。已尝试使用以下脚本,但未添加该行。

使用 add_trace 而不是 'add_lines' 无效。

df = data.frame(Aria = 20:25, Acqua = 21:26, Fuoco = 22:27, 
                Terra = 23:28, Cielo = 24:29, 
                Labels = c( 'Antonio', 'Maria', 'Giovanni',
                            'Sergio', 'Giorgio', 'Michele' ) )

evo_bar_plot_variant = function(plot_data, var_x, x_name = 'X axis', 
                                y_name = 'Y axis', ... ){
  df = data.frame(plot_data) 
  df = na.omit(df)
  var = quos(...) 
  names_vars = names( var )
  y_vars = names_vars[ startsWith( names_vars, 'var_y' ) ]
  y_var_names = sapply(1:length(y_vars), function(j){ 
                          quo_name(var[[y_vars[j]]] )})
  row_sum = df %>% 
              select( y_var_names ) %>% 
              rowSums()
  xenc = enquo( var_x )
  cols = colorRampPalette(c("white", "#4C68A2"))( length( y_vars ) )

  #... Plot parameters .....
  font_size = list( size = 12, family = 'Lato' )
  gray_axis = '#dadada'
  p = plot_ly(data = df, x = xenc, y = var[[ y_vars[1] ]], 
              name = quo_name( var[[ y_vars[1] ]] ), 
              type = 'bar', marker = list( color = cols[1], 
              line = list( color = '#E1E1E1', width = 0.8 ) ), 
              hoverlabel = list( font = font_size ) ) %>%
    layout(title = list( text = 'Bar', x = 0 ), barmode = 'stack',
           yaxis = list( title = y_name, showgrid = F, 
           zerolinecolor = gray_axis,
           titlefont = font_size, side = 'right' ),
           xaxis = list(title = x_name, linecolor = gray_axis,
                        zerolinecolor = gray_axis,
                        tickfont = font_size, titlefont = font_size),
           legend = list(font = font_size, orientation= 'h', 
                         font = font_size, x = 1 , y = 1.2, 
                         xanchor = "left", yanchor = 'top' ))

  if( length( y_vars ) >= 2 ){
    for( i in 2:length( y_vars ) ){
      p = p %>% 
            add_trace(y = var[[ y_vars[i] ]], 
                      name = quo_name( var[[ y_vars[i] ]] ), 
                      marker = list(color = cols[i], 
                      line = list(color = '#E1E1E1', width = 0.8)), 
                      hoverlabel = list(font = font_size))
    }
  }

  p =  p %>% 
        add_annotations(xref = 'x', yref = 'y', 
                        y = ( row_sum ) + 5, x = xenc,
                        text = paste( row_sum ), 
                        font = font_size, showarrow = F )

  p      
}

evo_bar_plot_variant( df, var_x = Labels, var_y1 = Aria, var_y2 = Acqua, var_y3 = Fuoco, var_y4 = Terra,
              var_y5 = Cielo )

得到这样的输出:

抱歉,我删除了您示例中的几行,因为它并不是真正的最小化。此外,我从 dplyr 切换到 data.table 因为我更熟悉它并且融化 table 让事情变得容易得多。

不过,还是希望以下内容对您有所帮助:

library(plotly)
library(data.table)

DF = data.frame(
  Aria = 20:25,
  Acqua = 21:26,
  Fuoco = 22:27,
  Terra = 23:28,
  Cielo = 24:29,
  Labels = c('Antonio', 'Maria', 'Giovanni',
             'Sergio', 'Giorgio', 'Michele')
)

setDT(DF)

DT <- melt.data.table(DF, id.vars = "Labels")
DT[, c("label_group", "cumsum_by_label") := .(.GRP, cumsum(value)), by = Labels]

lineDT <- rbindlist(list(DT[, .(
  label_group = label_group - 0.4,
  cumsum_by_label = cumsum_by_label,
  variable = variable
)],
DT[, .(
  label_group = label_group + 0.4,
  cumsum_by_label = cumsum_by_label,
  variable = variable
)]))

p <- plot_ly(
  DT,
  x = ~ label_group,
  y = ~ value,
  color = ~ variable,
  type = "bar",
  colors = ~ colorRampPalette(c("white", "#4C68A2"))(length(unique(variable)) + 1)[-1],
  legendgroup =  ~ variable,
  showlegend = TRUE
) %>%
  layout(
    title = list(text = 'Bar', x = 0),
    barmode = 'stack',
    legend = list(itemclick = FALSE, itemdoubleclick = FALSE)
  ) %>%
  layout(
    xaxis = list(
      title = "X axis",
      ticktext = ~ Labels,
      tickvals = ~ label_group,
      tickmode = "array"
    ),
    yaxis = list(title = "")
  ) %>%
  add_annotations(
    text = ~ value,
    xref = 'x',
    yref = 'y',
    y = ~ cumsum_by_label - value / 2,
    x = ~ label_group,
    showarrow = FALSE
  ) %>%
  add_annotations(
    data = DT[, .(maxval = max(cumsum_by_label),
                  label_group = unique(label_group)), by = Labels],
    inherit = FALSE,
    text = ~ maxval,
    xref = 'x',
    yref = 'y',
    y = ~ maxval,
    x = ~ label_group,
    showarrow = FALSE,
    yshift = 20
  ) %>%
  add_lines(
    data = lineDT,
    inherit = FALSE,
    x = ~ c(label_group),
    y = ~ cumsum_by_label,
    color = ~ variable,
    legendgroup =  ~ variable,
    showlegend = FALSE,
    hoverinfo = "none"
  )

p