Vertical vistime timeline and overlapping geom_text labels - r

I'm trying to draw a vertical timeline using vistime with its ggplot plotting option. My main intention is to better integrate it with text, side by side. This is the code:
library("vistime")
library("plotly")
data <- read.csv("../../data/programming.csv")
g <- gg_vistime(data, col.event="Item", col.start="Start.Date", col.end="End.Date", col.group="Group")
g + theme(axis.text.x = element_text(angle=90, color='blue4',size=14) )+coord_flip()
As you can see, as I'm doing the coord_flip, the labels intersect with each other. I'd like to make the labels go vertical. This is code that draws them:
https://github.com/shosaco/vistime/blob/372da36791cbdb7ad7d6841ed991e55b36f77e06/R/plot_ggplot.R#L83-L91
So that means that it's a geom_text sentence. Is there some way to change the orientation of geom_text-drawn text once it's done? Can I use some theme command to do that? Barring that, is there any way I can change the placement of the labels using vistime?

You can deconstruct any ggplot2 visualization with (surprisingly) ggplot_build (actually, what it does is to create elements that can be rendered using the plain vanilla plot).
data <- read.csv("data/programming.csv")
g <- gg_vistime(data, col.event="Item", col.start="Start.Date", col.end="End.Date", col.group="Group") + theme(axis.text.x = element_text(angle=90, color='blue4',size=14) )+coord_flip()
g.d <- ggplot_build(g)
g.d$data[[4]]$angle <- 90
rebuilt <- ggplot_gtable(g.d)
png(filename="img/timeline.png", width=240, height=960)
plot(rebuilt)
dev.off()
That creates a data frame with different elements of the plot, including g.d$data which contains, effectively, the data and its properties when rendered in its 4th element. g.d$data[[4]]$angle contains the angle of all the geom_text elements that have been rendered. So once you get that, it's just a matter of changing it individually or colectively to what you want. You need to reconstruct the plot using ggplot_gtable and then use the core plot command to plot and render it any way you want, in this case a png.
At any rate, ggplot_build allows you to introspect the data structures and different pieces of the graph created using ggplot, changing any one of its layers, metadata or pieces after they have been created. In our case, it produces the intended effect

Related

ggplot with the same width and height as ggsave(width=x, height=y)

Within R-Studio, I am generating plots with ggplot, then I save them with ggsave() for further use (I know, not ideal, but non-optional right now).
My problem is that when I generate the plot before saving it, R shows it to me in a particular size. With ggsave, I set width and height, so the elements displayed shift etc. I only see this after saving the plot.
I want R to show it to me before. I thus assume that I need to set the size of the plot within ggplot() somewhere , not in ggsave().
How can I do this in the least complicated fashion?
library(ggplot2)
ggplot(mtcars, aes(mpg,disp)) + geom_point() +
labs(title="Rocket science title that will get cut by ggsave")
ggsave("rocketScience.png", width=10, height=7, unit="cm")
You can use the set_panel_size() function from the egg package.
With this function you can fix the panel size of the plot. This can be very useful when creating multiple plots that should have the exact same plotting area but use varying axis labels or something similar that would usually slightly change the panel dimensions. Especially useful for presentations with seamless animations or publications. It also ensures the same dimensions in the preview and the saved plot.
p <- ggplot(mtcars, aes(mpg,disp)) +
geom_point() +
labs(title="Rocket science title that will get cut by ggsave")
#to view the plot
gridExtra::grid.arrange(egg::set_panel_size(p=p, width=unit(5, "cm"), height=unit(7, "cm")))
#to save the plot
ggsave(filename = "myplot.pdf", plot = egg::set_panel_size(p=p, width=unit(5, "cm"), height=unit(7, "cm")))
Within ggsave you can still manipulate the size of the whole "page" saved, but this will only influence the amount of white space around the plot. The actual panel size will stay fixed.
The example plot from above with 5cm or 15cm as width:
I don't believe this is achievable via ggplot settings; you might get around it if using RMarkdown, as you can set with and height of an output of a markdown chunk via fig.width and fig.height params.

How to move the legend to outside the plotting area in Plots.jl (GR)?

I have the following plot where part of the data is being obscured by the legend:
using Plots; gr()
using StatPlots
groupedbar(rand(1:100,(10,10)),bar_position=:stack, label="item".*map(string,collect(1:10)))
I can see that using the "legend" attribute, the legend can be moved to various locations within the plotting area, for example:
groupedbar(rand(1:100,(10,10)),bar_position=:stack, label="item".*map(string,collect(1:10)),legend=:bottomright)
Is there any way of moving the plot legend completely outside the plotting area, for example to the right of the plot or below it? For these kinds of stacked bar plots there's really no good place for the legend inside the plot area. The only solution I've been able to come up with so far is to make some "fake" empty rows in the input data matrix to make space with some zeros, but that seems kind of hacky and will require some fiddling to get the right number of extra rows each time the plot is made:
groupedbar(vcat(rand(1:100,(10,10)),zeros(3,10)),bar_position=:stack, label="item".*map(string,collect(1:10)),legend=:bottomright)
I can see that at there was some kind of a solution proposed for pyplot, does anyone know of a similar solution for the GR backend? Another solution I could imagine - is there a way to save the legend itself to a different file so I can then put them back together in Inkscape?
This is now easily enabled with Plots.jl:
Example:
plot(rand(10), legend = :outertopleft)
Using layouts I can create a workaround making a fake plot with legend only.
using Plots
gr()
l = #layout [a{0.001h}; b c{0.13w}]
values = rand(1:100,(10,10))
p1 = groupedbar(values,bar_position=:stack, legend=:none)
p2 = groupedbar(values,bar_position=:stack, label="item".*map(string,collect(1:10)), grid=false, xlims=(20,3), showaxis=false)
p0=plot(title="Title",grid=false, showaxis=false)
plot(p0,p1,p2,layout=l)

ggplotly created object does not dynamically adjust gridlines when zooming in

I'm trying to understand why plotly objects which are converted from ggplot2 objects using the ggplotly function do not dynamically rescale the grid when using plotly's zoom feature on the html widget.
I would like to find a solution to this without the need to recode all plots as native plotly objects.
Am I missing something, or could it be that this functionality is just not supported yet in the plotly package?
Here is some sample code illustrating the problem (before executing, you need to set the your.path variable to the directory you want the htmlwidget to be saved in):
library(ggplot2)
library(plotly)
library(htmlwidgets)
ggp <- ggplot(data=mtcars, aes(x=hp, y=mpg)) + geom_point() + theme_bw()
ply.ggp <- ggplotly(ggp)
saveWidget(ply.ggp, paste(your.path, "mtcarsGGPLOT.html", sep=""))
On this html widget when you zoom in, the grid scale remains static (e.g. the x grid lines on 100, 200, 300 are the only one you can see, even if you zoom in. There are no new grid lines visible e.g. at 25, 50, 75, etc.)
Compare this to the widget when creating the plot directly in plotly with this sample code:
ply <- plot_ly(data=mtcars, x=mtcars$hp, y=mtcars$mpg)
saveWidget(ply, paste(your.path, "mtcarsNATIVE.html", sep=""))
Here when you zoom in a region of the plot, a new dynamic grid is visible.
EDIT: Could it be that the observation occurs due to the htmlwidgets package rather than plotly or ggplot2. But then again, why would the native plotly graphic render correctly when using htmlwidgets while the ggplot converted one doesn't..?
I've also spent time trying to figure this out and it's actually quite simple.
Set dynamicTicks equal to TRUE within ggplotly.
ply.ggp <- ggplotly(ggp, dynamicTicks = TRUE)
I just tried creating the widget and it worked for me.

Hiding Data Point on qplot

I have downloaded the directlabels package in R to further enhance the ggplot2 experience, however I would like to delete the data point of a scatterplot once I have added the labels to them. Is there any way to hide these? My code goes something like this:
q<-qplot(x,y)+geom_point(aes(colour=z))
direct.label(q,list(cex=0.75,fontface="bold",bumpup))
But I'm not sure where the command to hide the data point would be. I would use first.qp but in this case I get the error
Error in order.labels(d) : labels are not aligned
so is there a better way of doing this?
You example is not reproducible. So I will just answer this question:
"I would like to delete the data point of a scatterplot once I
have added the labels to them."
You can easily for example remove a layer from the gg object. First I create a ggplot2 example and I decorate it using direct.label.
library(directlabels)
scatter <- qplot(jitter(hwy),jitter(cty),data=mpg,colour=class,
main="Fuel efficiency depends on car size")
scatter <- direct.label(scatter,list(cex=0.7,bumpup))
I remaove the first layer now(the geom_point layer)
scatter$layers[1] <- NULL
Then you get this plot , as you see I had only labels without points:
scatter

Adjusting the relative space of facets (without regard to coordinate space)

I have a primary graph and some secondary information that I want to facet in another graph below it. Facetting works great except I do not know how to control the relative space used by one facet versus another. Am aware of space='free' but this is only useful if the ranges correspond to the desired relative sizing.
So for instance, I may want a graph where the first facet occupies 80% and the second 20%. Here is an example:
data <- rbind(
data.frame(x=1:500, y=rnorm(500,sd=1), type='A'),
data.frame(x=1:500, y=rnorm(500,sd=5), type='B'))
ggplot() +
geom_line(aes(x=x, y=y, colour=type), data=data) +
facet_grid(type ~ ., scale='free_y')
The above creates 2 facets of equal vertical dimension. Adding in space='free' in the facet_grid function changes the dimensions such that the lower facet is roughly 5x larger than the upper (as expected).
Supposing I want the upper to be 2x as large, with the same data set and ordering of facets. How can I accomplish this?
Is the only way to do this with some trickery in rescaling the data set and manually overriding axis labels (and if so, how)?
Alternative
As indicated below can use viewports to render as multiple graphs. I had considered this and in-fact had implemented using this approach in the past with standard plot and viewports.
The problem is that it is very difficult to get x-axis to align with this approach. So if there is a way to fix the size of the y-axis label region and the size of the legend region, can produce 2 graphs that have the same rendering area.
You don't need to use facets for this - you can also do this by using the viewport function.
> ratio = 1/3
> v1 = viewport(width=1,height=ratio,y=1-ratio/2)
> v2 = viewport(width=1,height=1-ratio,y=(1-ratio)/2)
> print(qplot(1:10,11:20,geom="point"),vp=v1)
> print(qplot(1:10,11:20,geom="line"),vp=v2)
Ratio is the proportion of the top panel to the whole page. Try 2/3 and 4/5 as well.
This approach can get ugly if your legend or axis labels in the two plots are different sizes, but for a fix, see the align.plots function in the ggExtra package and ggplot2 author Hadley Wickam's notes on this very topic.
There's no easy way to do this with facets currently, although if you are prepared to go down to editing the Grid, you can modify the ggplot graph after it has been plotted to get this effect.
See also this question on using grid and ggplot2 to create join plots using R.
Kohske Takahashi posted a patch to facet_grid that allows specification of the relative sizing of facets. See the thread:
http://groups.google.com/group/ggplot2/browse_thread/thread/7c5454dcc04bc7b8
With luck we'll see this in a future version of ggplot2.

Resources