ggplotly with long names in the labels - r

I have data with long names which i would like to plot using ggplotly.
That's my code:
library(ggplot2)
library(plotly)
temp<-data.frame(x=c("longgggggggggggggggggggggggg_nameeeeeeeeeeeeeee1", "longggggggggggggggggggggggggg_nameeeeeeeeeeeeeee2"),
y=c(5,10))
break_str<-function(str,n){
if(nchar(str)<=n)
return(str)
ans<-""
for(i in 1:ceiling(nchar(str)/n)){
if(i<ceiling(nchar(str)/n)){
ans<-paste0(ans,substr(str,start=((i-1)*n+1),stop=min(i*n,nchar(str))),"\n")
} else{
ans<-paste0(ans,substr(str,start=((i-1)*n+1),stop=min(i*n,nchar(str))))
}
}
return(ans)
}
p <- ggplot(temp, aes(x=x, y=y)) +
labs(x="x",y="y") + geom_bar(stat="identity") + coord_flip() +
scale_x_discrete(labels = function(x) lapply(x,function(str){break_str(str,10)}))
ggplotly(p)
As you can see I use a custom break_str function which works similar to stringr::str_wrap but still it doesn't remove the margin in the plot.
This problem doesn't show up when in the ggplot version of p.
Any help would be appreciated
Thanks

Looks like you stumbled over a bug in ggplotly (maybe you should raise an issue on github). I had a look into the source code. The issue is that ggplotly does not take linebreaks in the tick labels into account when computing the margins. Hence, the margin is set too wide. This problem does not arise if you make the plot using plotly. However, as a simple workaround you can force automargin to do its job by adding the layout option margin = list(l = 0) like so:
ggplotly(p) %>%
layout(
margin = list(l = 0)
)
which results in this plot:

Related

For loop plot() vs ggplot() - ggplot() not working?

I am using Iris dataset in R.
I have the following code
for (i in colnames(iris[-5])) {
plot(iris$Species, iris[[i]],
xlab = 'Species',
ylab = `i`)
}
This prints out 4 boxplot.
I want to do the same in ggplot with the following code
for (i in colnames(iris[-5])) {
print(iris %>%
ggplot(aes(x = Species)) +
geom_col(aes(y = i)))
}
When I do this in ggplot, the boxplots look messed up. Is it just my R or am I missing something?
In this case, you can just change aes(y=i) to aes_string(y=i), and of course, use geom_boxplot instead of geom_col

How to place the strip in facet_grid on top of plots when plotting graphs vertically stacked - similar to position.strip = "top" in facet_wrap?

Using facet_grid(), how can I place the group names, i.e. the grey strips, on the top of the plots when graphing the plots stacked vertically in a single column?
From what I have tried, when stacking the plots vertically, using facet_grid(), you cannot place the strip on the top or bottom of the graph; you can only place the strip on the right hand side or the left hand side of the plots using the switch = c("y", "x", "both") argument.
I am aware that facet_wrap() (and facet_col() from ggforce) can place the strip anywhere using the strip.position = c("top", "bottom", "left", "right") argument, irrespective of how the graphs are being plotted: vertically or horizontally. I used facet_wrap() to produce Fig.1 below (code is in the Reproducible Code section).
However, I would like to be able to produce the plot below (with the strip on "top") using facet_grid() not facet_wrap.
Fig.1: I want to be able to plot this using facet_grid()
Ideally, it would be great if the switch argument could be extended or the strip.position argument could be added to facet_grid(), to be able to place the strip on top. I tried to do it myself by trying to change the source code from facet_grid() and facet_wrap() functions, but could not figure it out.
The reason I am not simply using facet_wrap() function is because it unfortunately does not have the space="free" argument which is available in facet_grid() and is essential in my application.
Below is a reproducible example taken from, with slight modifications, the code of Brandon Bertelsen answer's here:
Reproducible Code:
The Data:
dat <- data.frame(value=runif(30)*10,
grouping=c(rep("Group 1",10),
rep("Group 2",10),
rep("Group 3",10)),
letters=rep(LETTERS[1:10], 3)
Using facet_wrap to get strip on top when plotting graphs vertically:
ggplot(dat, aes(letters,value, label = letters)) +
geom_bar(stat="identity") +
facet_wrap(grouping~., dir = "v")
Produces Fig.1:
Using facet_grid with the switch = "y" places the strip to the left hand side:
ggplot(dat, aes(letters,value, label = letters)) +
geom_bar(stat="identity") +
facet_grid(grouping~., switch = "y")
Produces Fig.2:
Using facet_grid with the switch = "x" places the strip to the right hand side:
ggplot(dat, aes(letters,value, label = letters)) +
geom_bar(stat="identity") +
facet_grid(grouping~., switch = "x")
Produces Fig.3:
With no other options remaining I turn here for help.
Is that what you want? Then just leave sales = 'free' out.
library(ggplot2)
dat <- data.frame(value=runif(26)*10,
grouping=c(rep("Group 1",10),
rep("Group 2",10),
rep("Group 3",6)),
letters=LETTERS[1:26])
ggplot(dat, aes(letters,value, label = letters)) +
geom_bar(stat="identity") +
facet_wrap(grouping~., dir = "v")
Created on 2020-06-13 by the reprex package (v0.3.0)

Add space between mainPanel and sideerbarPanel in shiny

In the following shiny app, I want to add some spaces between mainPanel and a siderbarPanel in the bottom.
Here, I can't read the x axis ticks, I tried to rotate them but it doesnt improve the thing.
I also changed the height and width of the plotlyOutput but doesn't work.
I tried to add an HTML("<br><br><br>") but doesnt work too, the problem is probably from ggplot or plotly ?
My ggplot script is :
ggplot(data = df, aes(x = perimetre_commercial_estime,
y = nbr_ligne,
fill = perimetre_commercial_estime)) +
geom_bar(stat="identity") + theme_light() +
theme(axis.text.x=element_text(angle=30,hjust=1,vjust=0.5,size=6),
axis.title.x=element_blank(),
legend.position="top", legend.direction="horizontal") +
scale_fill_discrete("")
plotly doesnt support horizontal legend, so the graphic below is normal.
Thanks
This Plotly Setting Graph Size in R article might be helpful. Since you don't include all code, I cannot confirm entirely. Please let me know.
library(plotly)
library(dplyr)
gp = ggplot(
data = mtcars %>% add_rownames(),
aes( x = rowname, y = mpg )
) + geom_point() +
theme(axis.text.x=element_text(angle=30,hjust=1,vjust=0.5,size=6),
axis.title.x=element_blank())
ggplotly(gp) %>%
layout(
margin = list(
b=100
)
)

Hovermode using Plotly with R

Is there a way to code the hovermode when using plotly with R and ggplot2?
Currently, my code is:
plot <- ggplot(data, aes(var1, var2, text=var3)) +
geom_point()
py$ggplotly(plot)
And I want the plotly graph to automatically have the hover mode set to "show closest data on hover" rather than "compare data on hover".
The answer from 'mkcor' didn't work when trying to do the same in Shiny. I kept getting an 'unused argument' error. For anyone else with the same problem, this worked for me...
Suppose this is my basic plot:
p <- ggplot(myDf, aes(x=x, y=y )) + geom_point(size = 3, shape = 0)
You can convert the ggplot object to a plotly object:
ggObj <- plotly(p)
Then you can change the hovermode like this:
layout(ggObj, hovermode = 'closest')
Add the following argument when calling ggplotly:
py$ggplotly(plot, kwargs=list(layout=list(hovermode="closest")))

Date labels overlap when putting multiple ggplot plots on single page

I am trying to put multiple ggplot2 time series plots on a page using the gridExtra package's arrange() function. Unfortunately, I am finding that the x-axis labels get pushed together; it appears that the plot is putting the same number of x-axis labels as a full-page chart, even though my charts only take up 1/4 of a page. Is there a better way to do this? I would prefer not to have to manually set any points, since I will be dealing with a large number of charts that span different date ranges and have different frequencies.
Here is some example code that replicates the problem:
dfm <- data.frame(index=seq(from=as.Date("2000-01-01"), length.out=100, by="year"),
x1=rnorm(100),
x2=rnorm(100))
mydata <- melt(dfm, id="index")
pdf("test.pdf")
plot1 <- ggplot(mydata, aes(index, value, color=variable))+geom_line()
plot2 <- ggplot(mydata, aes(index, value, color=variable))+geom_line()
plot3 <- ggplot(mydata, aes(index, value, color=variable))+geom_line()
plot4 <- ggplot(mydata, aes(index, value, color=variable))+geom_line()
arrange(plot1, plot2, plot3, plot4, ncol=2, nrow=2)
dev.off()
either rotate the axis labels
+ opts(axis.text.x=theme_text(angle=45, hjust=1))
Note that opts is deprecated in current versions of ggplot2. This functionality has been moved to theme():
+ theme(axis.text.x = element_text(angle = 45, hjust = 1))
or dilute the x-axis
+scale_x_datetime(major = "10 years")
to automatically shift the labels, I think the arrange() function needs to be fiddled with (though I'm not sure how).
I wrote this function to return the proper major axis breaks given that you want some set number of major breaks.
year.range.major <- function(df, column = "index", n = 5){
range <- diff(range(df[,column]))
range.num <- as.numeric(range)
major = max(pretty((range.num/365)/n))
return(paste(major,"years"))
}
So, instead of always fixing the breaks at 10 years, it'll produce fixed number of breaks at nice intervals.
+scale_x_date(major = year.range.major())
or
+scale_x_date(major = year.range.major(n=3))

Resources