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.
Related
I found this on the Tidyverse Github:
https://github.com/tidyverse/ggplot2/issues/3716
but I can't find the resolution of yutannihilation's question.
For exploratory data analysis, I would like for the outline stroke to reach the x-axis as it does with base R, including facets with scales="free".
Is there a way to do this programmatically? The user may have multiple facets of data, on the same or different scales. Can I ensure the x-axis is wide enough to take the density to zero?
I have tried outline.type = "full" and "both" but neither seem to work.
The MRE shows the issue. The use case is within a Shiny app and can be facet_wrap-ed as well.
Thanks!
#R base
plot(density(diamonds$carat, adjust = 5))
#ggplot
library(ggplot2)
ggplot(diamonds, aes(carat)) +
geom_density(adjust = 5)
A straightforward solution would be to calculate the density yourself and plot that:
library(ggplot2)
ggplot(as.data.frame(density(diamonds$carat, adjust = 5)[1:2]), aes(x, y)) +
geom_line()
In ggplot2, the coord_fixed() coordinate system ensures that the aspect ratio of the data is maintained at a given value. So, the shape of the panel changes to maintain the shape of the data. Meanwhile coord_flip() swaps the axes of the plot. However, a plot in ggplot2 must have exactly one coordinate system, so these functions cannot be combined.
My question is:
Does there exist a way to combine the behaviours of coord_fixed() and coord_flip(), resulting in a coordinate system with the x and y axes exchanged and a fixed aspect ratio of the data?
This is a popular question, however the common answer is incorrect:
How do I to fix aspect ratio and apply coord_flip in ggplot2?
Flipping and maintaining aspect ratio of a chart in ggplot2
The commonly suggested answer is to use coord_flip() together with theme(aspect.ratio = 1) instead of coord_fixed(). However, as per the ggplot2 documentation, this setting refers to the "aspect ratio of the panel." Thus, the data will change shape to maintain the shape of the panel.
I suspect that this is a feature that does not currently exist in ggplot2. But more importantly I think that a correct solution or at least response to this question should be documented.
Quick minimal example of the issue:
library(ggplot2)
x <- 1:100; data <- data.frame(x = x, y = x * 2)
p <- ggplot(data, aes(x, y)) + geom_point()
p # by default panel and data both fit to device window
p + coord_fixed() # panel changes shape to maintain shape of data
p + theme(aspect.ratio = 1) # data changes shape to maintain shape of panel
p + coord_fixed() + coord_flip() # coord_flip() overwrites coord_fixed()
# popular suggested answer does not maintain aspect ratio of data:
p + coord_flip() + theme(aspect.ratio = 1)
I agree that the theme solution isn't really a proper one. Here is a solution that does work programatically by calculating the aspect from the actual axes ranges stored in the plot object, but it takes a few lines of code:
ranges <- ggplot_build(p)$layout$panel_ranges[[1]][c('x.range', 'y.range')]
sizes <- sapply(ranges, diff)
aspect <- sizes[1] / sizes[2]
p + coord_flip() + theme(aspect.ratio = aspect)
The solution I would probably use in practice, is to use the horizontal geoms in the ggstance package (although this may not always be feasible).
Note: This will only give the exact correct answer for two continuous scales with an equal multiplicative extend argument (i.e. the default).
edit: In many cases I would recommend using coord_equal combined with the ggstance package instead of this solution.
I ended up just flipping the x and y arguments in the aes specification. So for example instead of:
ggplot(mtcars,aes(x=wt,y=drat))+geom_point()+coord_fixed()
I did:
ggplot(mtcars,aes(x=drat,y=wt))+geom_point()+coord_fixed()
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")]
Let's say I have this data.frame:
df <- data.frame(x = rep(1, 20), y = runif(20, 10, 20))
and I want to plot df$y vs. df$x.
Since the x values are constant, points that have identical or close y values will be plotted on top of each other in a simple scatterplot, which kind of hides the density of points at such y-values. One solution for that situation is of course to use a violin plot.
I'm looking for another solution - plotting clusters of points instead of the individual points, which will therefore look similar to a bubble plot. In a bubble plot however, a third dimension is required in order to make the bubbles meaningful, which I don't have in my data. Does anyone know of an R function/package that take as input points (and probably a defined radius) and will cluster them and plot them?
You can jitter the x values:
plot(jitter(df$x),df$y)
You could try a hexplot, using either the hexplot library or stat_binhex in ggplot2.
http://cran.r-project.org/web/packages/hexbin/
http://docs.ggplot2.org/0.9.3/stat_binhex.html
The other standard approach (vs. jitter) is to use a partially transparent color, so that overlapping points will appear darker than "lone" points.
De gustibus, etc.
Using transparency is another solution. E.g.:
ggplot(df, aes(x=x, y=y)) +
geom_point(alpha=0.2, size=3)
When there is only one x value, a density plot:
ggplot(df, aes(x=y)) +
stat_density(geom="line")
or a violin plot:
ggplot(df, aes(x=x, y=y)) +
geom_violin()
might also be options for displaying your data.
look at the sunflowerplot function (and the xyTable function that it uses to count overlapping points).
You could also use the my.symbols function from the TeachingDemos package with the results of xyTable to use other shapes (polygrams or example).
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.