ggplot query or change plot limits - r

I have a ggplot object returned by a function in an R package. I want to add some elements to this plot before plotting it. But, I do not know the plot limits. Is there a way to query the ggplot object to find the plot limits? Actually, what I'd really like to do is simply set new limits for subsequent plotting, but I understand this is not possible, based on discussions of the impossibility of plotting data against two different y-axes.
For example, say I want to plot a small rectangle in lower-left corner of plot, but not knowing the plot limits, I don't know where to put it:
p = function() return(ggplot() + xlim(-2, 5) + ylim(-3, 5) +
geom_rect(mapping=aes(xmin=1, xmax=2, ymin=1, ymax=2)))
gp = p()
gp = gp + geom_rect(mapping=aes(xmin=0, ymin=0, xmax=0.5, ymax=0.5))
print(gp)

In ggplot2 3.0.0:
ggplot_build(gp)$layout$panel_params[[1]][c("x.range","y.range")]

ggplot_build(p)$layout$panel_ranges[[1]][c("x.range","y.range")]

Related

ggplot: plot title and plot overlap each other

I am a newbie to R and hence having some problems in plotting using ggplot and hence need help.
In the above diagram, if any of my bars have high values (in this case, a green one with value of 447), the plot and the plot title gets overlapped. The values here are normalised / scaled such that the y-axis values are always between 0-100, though the label might indicate a different number (this is the actual count of occurrences, where as the scaling is done based on percentages).
I would like to know how to avoid the overlap of the plot with the plot title, in all cases, where the bar heights are very close to 100.
The ggplot function I am using is as below.
my_plot<-ggplot(data_frame,
aes(x=as.factor(X_VAR),y=GROUP_VALUE,fill=GROUP_VAR)) +
geom_bar(stat="identity",position="dodge") +
geom_text(aes(label = BAR_COUNT, y=GROUP_VALUE, ymax=GROUP_VALUE, vjust = -1), position=position_dodge(width=1), size = 4) +
theme(axis.text.y=element_blank(),axis.text.x=element_text(size=12),legend.position = "right",legend.title=element_blank()) + ylab("Y-axis label") +
scale_fill_discrete(breaks=c("GRP_PERCENTAGE", "NORMALIZED_COUNT"),
labels=c("Percentage", "Count of Jobs")) +
ggtitle("Distribution based on Text Analysis 2nd Level Sub-Category") +
theme(plot.title = element_text(lineheight=1, face="bold"))
Here is the ggsave command, in case if that is creating the problem, with dpi, height and width values.
ggsave(my_plot,file=paste(paste(variable_name,"my_plot",sep="_"),".png",sep = ""),dpi=72, height=6.75,width=9)
Can anyone please suggest what need to be done to get this right?
Many Thanks
As Axeman suggests ylim is useful Have a look at the documentation here:
http://docs.ggplot2.org/0.9.3/xylim.html
In your code:
my_plot + ylim(0,110)
Also, I find this intro to axis quite useful:
http://www.cookbook-r.com/Graphs/Axes_(ggplot2)/
Good luck!

Plot log density of a distribution in ggplot2 [duplicate]

I'm using ggplot as described here
Smoothed density estimates
and entered in the R console
m <- ggplot(movies, aes(x = rating))
m + geom_density()
This works but is there some way to remove the connection between the x-axis and the density plot (the vertical lines which connect the density plot to the x-axis)
The most consistent way to do so is (thanks to #baptiste):
m + stat_density(geom="line")
My original proposal was to use geom_line with an appropriate stat:
m + geom_line(stat="density")
but it is no longer recommended since I'm receiving reports it's not universally working for every case in newer versions of ggplot.
The suggested answers dont provide exactly the same results as geom_density. Why not draw a white line over the baseline?
+ geom_hline(yintercept=0, colour="white", size=1)
This worked for me.
Another way would be to calculate the density separately and then draw it. Something like this:
a <- density(movies$rating)
b <- data.frame(a$x, a$y)
ggplot(b, aes(x=a.x, y=a.y)) + geom_line()
It's not exactly the same, but pretty close.

tiny pie charts to represent each point in an scatterplot using ggplot2

I want to create a scatter plot, in which each point is a tiny pie chart. For instance consider following data:
foo <- data.frame(X=runif(30), Y=runif(30),A=runif(30),B=runif(30),C=runif(30))
The following code will make a scatter plot, representing X and Y values of each point:
library(reshape2)
library(ggplot2)
foo.m <- melt(foo, id.vars=c("X","Y"))
ggplot(foo.m, aes(X,Y))+geom_point()
And the following code will make a pie chart for each point:
p <- ggplot(foo.m, aes(variable,value,fill=variable)) + geom_bar(stat="identity")
p + coord_polar() + facet_wrap(~X+Y,,ncol=6) + theme_bw()
But I am looking to merge them: creating a scatter plot in which each point is replaced by the pie chart. This way I will be able to show all 5 values (X, Y, A, B, C) of each record in the same chart.
Is there anyway to do it?
This is the sort of thing you can do with package ggsubplot. Unfortunately, according to issue #10 here, this package is not working with R 3.1.1. I ran it successfully if I used an older version of R (3.0.3).
Using your long dataset, you could put bar plots at each X, Y point like this:
library(ggplot2)
library(ggsubplot)
ggplot(foo.m) +
geom_subplot2d(aes(x = X, y = Y,
subplot = geom_bar(aes(variable, value, fill = variable), stat = "identity")),
width = rel(.5), ref = NULL)
This gives the basic idea, although there are many other options (like controlling where the subplots move to when there is overlap in plot space).
This answer has more information on the status of ggsubplot with newer R versions.
there is a package, scatterpie, that does exactly what you want to do!
library(ggplot2)
library(scatterpie)
ggplot() +
geom_scatterpie(aes(x=X, y=Y, r=0.1), data=foo.m, cols=c("A", "B", "C"))
In the aesthetics, r is the radius of the pie, you can adjust as necessary. It is dependent on the scale of the graph - since your graph goes from 0.0 to 1.0, a radius of 1 would take up the entire graph (if centered at 0.5, 0.5).
Do note that while you will get a legend for the pie slice colors, it will not (to my knowledge) label the slices themselves on the pies.

rdata & ggplot: specifying plot initial plot size?

I'm using ggplot2 and attempting to create an empty plot with some basic dimensions, like I might do w/ the stock plot function like so:
plot(x = c(0, 10), y=c(-7, 7))
Then I'd plot the points with geom_point() (or, stock point() function)
How can I set that basic plot up using ggplot? I'm only able to draw a plot using like:
ggplot() + layer(data=data, mapping = aes(x=side, y=height), geom = "point")
But this has max x/y values based on the data.
There are two ways to approach this:
Basically the same approach as with base graphics; the first layer put down has the limits you want, using geom_blank()
ggplot() +
geom_blank(data=data.frame(x=c(0,10),y=c(-7,7)), mapping=aes(x=x,y=y))
Using expand_limits()
ggplot() +
expand_limits(x=c(0,10), y=c(-7,7))
In both cases, if your data extends beyond this, the axes will be further expanded.
You can set the overall plotting region limits using xlim and ylim:
ggplot(data = data) +
geom_point(aes(x = side, y = height) +
xlim(c(0,10)) +
ylim(c(-7,7))
Also see coord_cartesian which zooms in and out rather than hard coding the axis limits.
Edit Since #Brian clarified the differences between his answer and mine well, I thought I should mention it as well in my answer, so no one misses it. Using xlim and ylim will set the limits of the plotting region no matter what data you add in subsequent layers. Brian's method using expand_limits is a way to set the minimum ranges.

scatterplot with equal axes

I have a data set like this one below:
DataFrame <- data.frame(x=runif(25),y=runif(25),
z=sample(letters[1:4],25,rep=TRUE))
and using the Lattice package, I can make a scatter plot with equal axes (with a 1:1 line going through the centre) with the following lines:
xyplot(y ~ x | z, data=DataFrame,
scales=list(relation="free"),
prepanel=function(x,y,...) {
rg <- range(na.omit(c(x,y)))
list(xlim=rg,ylim=rg)
},panel=function(x,y,...) {
panel.abline(0,1)
panel.xyplot(x,y,...)
})
In ggplot2, I have gotten this far:
ggplot(data=DataFrame) + geom_point(aes(x=x,y=y)) +
facet_grid(~z,scales="free") + coord_equal(ratio=1) +
geom_abline(intercept=0,slope=1)
But I'm not sure that coord_equal() is the function I'm looking for. What might be the equivalent function call in ggplot2?
Your problem lies in setting free facet scales. Once you set the facet scales to be free, you can't then add coord_equal() If you eliminate the free scales, then coord_equal() works properly.
Maybe facet_wrap() is a better choice, and as far as I know the control of xlim and ylim for individual panels is not available in ggplot2.

Resources