Keep conditional and square aspect ratio in ggplotly ()

I am trying to create a plot that contains a legend and a square shape with equal aspect ratio. I was able to achieve this in the "p" object in the code below using ggplot2 (). However, when I ran ggplotly () on the "p" object, the legend disappeared, and the equal aspect ratio square shape also disappeared. Below I show two images showing the difference. The left image shows object "p" with legend and equal aspect ratio. The x = y line in red intersects the lower-left and upper-right corners of the image perfectly. The correct image shows the output of ggplotly (p) where the legend is gone and the square aspect ratio is also gone. The x = y line no longer perfectly intersects the lower left and upper right corners of the image.

Comparison of two graphs

My MWE code is below:

library(hexbin)
library(ggplot2)
library(plotly)
set.seed(1)
dat <- data.frame(ID = paste0("ID", 1:1010), A.1 = c(rep(0.5, 1000), abs(rnorm(10))), A.2 = c(rep(0.5, 1000), abs(rnorm(10))), B.1 = c(rep(0.5, 1000), abs(rnorm(10))), B.2 = c(rep(0.5, 1000), abs(rnorm(10))), C.1 = c(rep(0.5, 1000), abs(rnorm(10))), C.2 = c(rep(0.5, 1000), abs(rnorm(10))), C.3 = c(rep(0.5, 1000), abs(rnorm(10))), stringsAsFactors = FALSE
)

sampleIndex <- which(sapply(colnames(dat), function(x) unlist(strsplit(x,"[.]"))[1]) %in% c("A", "C"))
datSel <- dat[,c(1, sampleIndex)]

sampleIndex1 <- which(sapply(colnames(datSel), function(x) unlist(strsplit(x,"[.]"))[1]) %in% c("A"))
sampleIndex2 <- which(sapply(colnames(datSel), function(x) unlist(strsplit(x,"[.]"))[1]) %in% c("C"))
minVal = min(datSel[,-1])
maxVal = max(datSel[,-1])
maxRange = c(minVal, maxVal)
xbins= 10
buffer = (maxRange[2]-maxRange[1])/(xbins/2)
x <- c()
y <- c()
for (i in 1:length(sampleIndex1)){
  for (j in 1:length(sampleIndex2)){
    x <- c(x, unlist(datSel[,(sampleIndex1[i])]))
    y <- c(y, unlist(datSel[,(sampleIndex2[j])]))
  }
}

h <- hexbin(x=x, y=y, xbins=xbins, shape=1, IDs=TRUE, xbnds=maxRange, ybnds=maxRange)
hexdf <- data.frame (hcell2xy (h),  hexID = h@cell, counts = h@count)
attr(hexdf, "cID") <- h@cID

my_breaks = c(2, 4, 6, 8, 20, 1000)
p <- ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID)) + geom_hex(stat="identity") + geom_abline(intercept = 0, color = "red", size = 0.25) + labs(x = "A", y = "C") + coord_fixed(xlim = c(-0.5, (maxRange[2]+buffer)), ylim = c(-0.5, (maxRange[2]+buffer))) + theme(aspect.ratio=1)
p <- p + scale_fill_gradient(name = "count", trans = "log", breaks = my_breaks, labels = my_breaks, guide="legend")

ggplotly(p)
ggplotly(p) %>% layout(height = 200, width = 200)
ggplotly(p, height=400, width=400)

      

As you can see, I tried several different approaches for generating ggplotly (p) output. I got warnings like this:

 Warning messages:
1: Aspect ratios aren't yet implemented, but you can manually set a suitable height/width 
2: Aspect ratios aren't yet implemented, but you can manually set a suitable height/width 
3: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly() 

      

However, I am not sure how to resolve this warning and issue. Any suggestions would be greatly appreciated!

+3


source to share


1 answer


This is a partial solution, it fixes the x to y aspect ratio and the square aspect ratio, but uses a little workaround for the legend issue.

The problem with the aspect ratio is simple, the latest version of the plot has changed so that now height =

and width =

go in ggplotly()

, and not layout()

, as in the previous version. Unfortunately, some of the online documentation still points to old formatting.

I couldn't get your normal legend and scale to show in the plot, and the incompatibility with ggplot legends seems to be a documented plot bug for some ggplots types. The best solution I could think of is to create a column in your log counting framework and then calculate the number of logs so that by default the legend shows the colors and scale you want.



# add a column for log count so default scale/legend can be used
hexdf$log_counts <- log(hexdf$counts)

p <- ggplot(hexdf, aes(x = x, y = y)) +
  geom_hex(stat="identity", aes(fill = log_counts)) + # log counts, not  counts
  geom_abline(intercept = 0, color = "red", size = 0.25) +
  labs(x = "A", y = "C") +
  coord_fixed(xlim = c(-0.5, (maxRange[2]+buffer)),
              ylim = c(-0.5, (maxRange[2]+buffer))) +
  theme(aspect.ratio = 1)

p 

# set width > height to allow room for legend
# plot looks close to 1:1 to me, but may need to adjust width slightly
ggplotly(p, height = 400, width = 500) 

      

What produces

enter image description here

+4


source







All Articles