Converting ggplot object to plotly object creates

2019-08-09 05:46发布

I had the same issue described in this question:

R: ggplot and plotly axis margin won't change

but when I implemented the solution, I got the following error:

Warning: Ignoring unknown aesthetics: text We recommend that you use the dev version of ggplot2 with ggplotly() Install it with: devtools::install_github('hadley/ggplot2') Error in tmp[[2]] : subscript out of bounds

This code will produce this error on my machine:

library(gapminder)
library(plotly)
library(ggplot2)

lead <- rep("Fred Smith", 30)
lead <- append(lead, rep("Terry Jones", 30))
lead <- append(lead, rep("Henry Sarduci", 30))
proj_date <- seq(as.Date('2017-11-01'), as.Date('2017-11-30'), by = 'day')
proj_date <- append(proj_date, rep(proj_date, 2))
set.seed(1237)
actHrs <- runif(90, 1, 100)
cummActHrs <- cumsum(actHrs)
forHrs <- runif(90, 1, 100)
cummForHrs <- cumsum(forHrs)
df <- data.frame(Lead = lead, date_seq = proj_date,
                 cActHrs = cummActHrs,
                 cForHrs = cummForHrs)

makePlot <- function(dat=df, man_level = 'Lead') {
    p <- ggplot(dat, aes_string(x='date_seq', y='cActHrs',
                               group = man_level,
                               color = man_level),
                linetype = 1) +
         geom_line() +
         geom_line(data=df,
                   aes_string(x='date_seq', y = 'cForHrs',
                              group = man_level,
                              color = man_level),
                   linetype = 2)

    p <- p + geom_point(aes(text=sprintf('%s\nManager: %s\n MTD Actual Hrs: %s\nMTD Forecasted Hrs: %s',
                                         date_seq, Lead, round(cActHrs, 2), round(cForHrs, 2))))

    p <- p + theme_classic() + ylab('Hours') + xlab('Date')

    gp <- ggplotly(p, tooltip = "text") %>% layout(hovermode = "compare")
    ### FIX IMPLEMENTED HERE ###
    gp[['x']][['layout']][['annotations']][[2]][['x']] <- -0.1
    gp %>% layout(margin = list(l = 75))

    return(gp)
}

## run the example
p1 <- makePlot()

2条回答
够拽才男人
2楼-- · 2019-08-09 05:50

Try this:

makePlot <- function(dat=df, man_level = "Lead") {
  dat$var <- dat[,man_level]
  dat$grp <- ""
  p <- ggplot(dat, aes(x=date_seq, y=cActHrs,
              group = var, color = var,
              text=paste0("Manager:", date_seq,"<br>MTD Actual Hrs:", round(cActHrs, 2),
                          "<br>MTD Forecasted Hrs:", round(cForHrs, 2))),
              linetype = 1) +
       geom_line() +
       geom_line(data=dat,
                 aes(x=date_seq, y = cForHrs,
                     group = var, color = var),
                 linetype = 2) +
        geom_point() +
        theme_classic() + ylab("Hours") + xlab("Date") +
        scale_color_discrete(name=man_level) +
        facet_wrap(~grp)

    gp <- ggplotly(p, tooltip = "text") 
    # Set y-axis label position
    gp[["x"]][["layout"]][["annotations"]][[2]][["x"]] <- -0.06
    # Set legend label position    
    gp[["x"]][["layout"]][["annotations"]][[3]][["y"]] <- 0.93
    gp <- gp %>% layout(margin = list(l = 120, b=70), hovermode = "compare")

    return(gp)
}

enter image description here

查看更多
3楼-- · 2019-08-09 06:11

The problem in your case is the opposite of the linked question. Your axis title is a real axis title, not an annotation. Currently there is no solution to move axis titles in any direction (see https://github.com/lleslie84/plotly.js/pull/1).

Workarounds like adding line breaks to the axis title or adding spaces to the tick labels don't work in your case.

One possible workaround would be to add an annotation with your axis title. The annotation can then be freely moved.

gp <- layout(gp, yaxis = list(title = ""),
             margin = list(l = 100), 
             annotations = c(list(text = "Hours",
                                  x = -0.15,
                                  xref = "paper",
                                  showarrow = F,
                                  textangle = -90))
  )

enter image description here

Complete code

library(gapminder)
library(plotly)
library(ggplot2)

lead <- rep("Fred Smith", 30)
lead <- append(lead, rep("Terry Jones", 30))
lead <- append(lead, rep("Henry Sarduci", 30))
proj_date <- seq(as.Date('2017-11-01'), as.Date('2017-11-30'), by = 'day')
proj_date <- append(proj_date, rep(proj_date, 2))
set.seed(1237)
actHrs <- runif(90, 1, 100)
cummActHrs <- cumsum(actHrs)
forHrs <- runif(90, 1, 100)
cummForHrs <- cumsum(forHrs)
df <- data.frame(Lead = lead, date_seq = proj_date,
                 cActHrs = cummActHrs,
                 cForHrs = cummForHrs)

makePlot <- function(dat=df, man_level = 'Lead') {
  p <- ggplot(dat, aes_string(x='date_seq', y='cActHrs',
                              group = man_level,
                              color = man_level),
              linetype = 1) +
    geom_line() +
    geom_line(data=df,
              aes_string(x='date_seq', y = 'cForHrs',
                         group = man_level,
                         color = man_level),
              linetype = 2)

  p <- p + geom_point(aes(text=sprintf('%s\nManager: %s\n MTD Actual Hrs: %s\nMTD Forecasted Hrs: %s',
                                       date_seq, Lead, round(cActHrs, 2), round(cForHrs, 2))))

  p <- p + theme_classic() + ylab('Hours') + xlab('Date')

  gp <- ggplotly(p, tooltip = "text") %>% layout(hovermode = "compare")

  ### FIX IMPLEMENTED HERE ###
  gp <- layout(gp,
               yaxis = list(title = ""),
               margin = list(l = 100),
               annotations = c(list(text = "Hours",
                                    x = -0.15,
                                    xref = "paper",
                                    showarrow = F,
                                    textangle = -90))
  )

  return(gp)
}

## run the example
p1 <- makePlot()
p1
查看更多
登录 后发表回答