Can I set a minimum font size in geom_text? - r

I am constructing a scatter plot with variables x and y. Each point is labelled using geom_text. The size of geom_text is controlled by a third variable z.
Is there a way to specify the minimum acceptable font size? I have looked at this question but it only discusses how to set the size to a fixed value.
In the example below, I have reproduced the issue using mtcars, with the size of geom_text controlled by 'disp'. It works, but some of the labels are too small to read (once the value of 'disp' gets lower than about 100).
library(ggplot2)
ggplot(mtcars, aes(y=mpg, x=cyl)) + geom_text(aes(label=rownames(mtcars),size=disp))
I'd like to be able to specify, for example, that the size is controlled by the value of 'disp', but that it should be no smaller than 3.
Obviously this would mean that the larger text was scaled up too.

You can set the range in scale_size
ggplot(mtcars, aes(y=mpg, x=cyl)) +
geom_text(aes(label=rownames(mtcars),size=disp)) +
scale_size(range = c(6, 9))
# a little more reasonable
ggplot(mtcars, aes(y=mpg, x=cyl)) +
geom_text(aes(label=rownames(mtcars),size=disp)) +
scale_size(range = c(2, 5))

Related

How to plot a scatter plot with a radius given by a variable?

I'm pretty new to ggplot, I need to make a scatterplot with the size proportional to a variable of the df, so that some of the points get "zero radius" because a 0 value in the variable, but when I use the size aes, the points with 0 value are mapped to a non-zero radius point.
how can I get the desired effect?
According to the help, "scale_size_area ensures that a value of 0 is mapped to a size of 0". [Also worth noting, you can get a similar effect if you use scale_radius or scale_size and set the lower limit of the range argument to zero]. So we can do:
df <- data.frame(x=0:5, y=0:5, s=0:5)
ggplot(df, aes(x=x, y=y)) +
geom_point(aes(size=s)) +
scale_size_area() # NB scale_size(range = c(0, 6)) also works
Note that this still shows the location of 'zero size' points using a single pixel. If you want them to be actually invisible, you can filter out the rows of zero size like this:
ggplot(df, aes(x=x, y=y, size=s)) +
geom_point(data = df[df$s != 0,]) +
scale_size_area()

Map size to more than one variable with geom_point in ggplot2

Is there any option to use two variables in parameter size in ggplot function?
E.g.
ggplot(mtcars, aes(qsec,drat, size = cyl))+
geom_point()
Obviously it works and size of points depends on cyl variable. But is it any option to add another size variable which can use alpha option e.g. variable = mpg. How to do it?
I did it just for three dots as an example in Ilustrator.
Thanks,
Update
Thanks to #lukeA following lines of code works:
ggplot() +
geom_point(data = mtcars, aes(qsec,drat, size = cyl)) +
geom_point(data = mtcars, aes(qsec,drat, size = mpg), alpha = .1, colour = "red")
But when I want to set the size of each variable separately, it is not possible. When there is one size variable normally I use scale_size_contiunous but with two size variables it doesn't work. I know that using scale_size_continuous two times doesn't change anything. Maybe it is not possible at all, but maybe somebody find the solution.
You can do this now with ggnewscale - allowing you to have more than one scale for any aesthetic. The scales can be defined separately too. Here's an example:
library(ggplot2)
library(ggnewscale)
ggplot(mtcars, aes(x=qsec, y=drat)) + theme_bw() +
geom_point(aes(size=cyl), color='gray20') +
scale_size_continuous(range=c(0.2, 3)) +
new_scale("size") +
geom_point(aes(size=mpg), alpha=0.1, color='red') +
scale_size_continuous(range=c(5, 10))
You can define the ranges for each scale separately. In this case, that's important so that you can ensure that the range of sizes mapped to mpg is larger than the range of sizes mapped to cyl. Otherwise, both are mapped to the default range (c(1,6)), which means many points would not have a visible red point.

howto: Automatically set fixed coordinate ratio (coord_fixed) when x- and y-axis are on different scales?

My goal is to fix the coordinate aspect ratio of a plot from ggplot2 via coord_fixed(). I thought coord_fixed(ratio=1) did the job independently of the scales of the x- or y-axis. My intuition: the argument ratio refers to the ratio of the total range of coordinate x to the total range of coordinate y. Implying that a ratio of 1 always means that the x-axis will be as long as the y-axis in the plot.
Yet with x-coordinates in the 1000s and y-coordinates e.g. percent, coord_fixed does not behave not as I expect it.
2 Questions:
Can you explain why coord_fixed takes the actual scale of the data into account but not the coordinate length as a whole?
Can I change the coord_fixed programatically to always refer to the whole range of the x- and y-coordinate values?
Here's an illustration
library("ggplot2")
set.seed(123)
df = data.frame(x=runif(11)*1000,y=seq(0,.5,.05))
ggplot(df, aes(x,y)) +geom_point() +coord_fixed(1)
produces
Rescaling the data by the ratio of x- and y-values in coord-fixed solves the issue
ggplot(df, aes(x,y)) +geom_point() +coord_fixed(1*max(df$x)/max(df$y))
However, this is not progammatically. I would have to specify the df$x manually to achieve the desired effect. See question 2: Is there a sensible way to automatize the re-scaling of the coordinates within coord_fixed depending on which data is on the x-/y-axis in my ggplot plot?
Can you plain why coord_fixed takes the actual scale of the data into account but not the coordinate length as a whole?
That's the point of coord_fixed. It's especially useful when, e.g., x and y are measures of length in the same units. (Basically whenever x and y have the same units, coord_fixed with ratio = 1 is what you want.)
For example, if my data is a square and a triangle, coord_fixed is the only way to make the square actually square
shapes <- data.frame(x = c(1, 1, 2, 2, 1, 3, 3, 4, 3),
y = c(1, 2, 2, 1, 1, 1, 2, 1, 1),
name = c(rep("square", 5), rep("isosceles triangle", 4)))
shape.plot <- ggplot(shapes, aes(x = x, y = y, group = name, color = name)) +
geom_path()
shape.plot # distorted
shape.plot + coord_fixed() # square!
Can I change the coord_fixed programatically to always refer to the whole range of the x- and y-coordinate values?
I would recommend not overwriting it, you could try to create your own version much as in your answer (though if you want to pull the appropriate values out of the x and y specifications of aes() you'll have a challenge---and you'll learn more about ggplot's internal workings than I know). However, the default behavior (without specifying any coord) seems to be what you're looking for.
If you compare
# your code
ggplot(df, aes(x,y)) + geom_point() + coord_fixed(1 * max(df$x) / max(df$y))
# no coord at all
ggplot(df, aes(x,y)) + geom_point()
they're basically the same. So, the modification of coord_fixed you seem to be looking for is don't use coord_fixed.
Aspect ratio of plot area (independent of coordinates): don't use coord_fixed
Just found out about this from this semi-related post: if you want a specific aspect ratio of the plot area, you can get it with theme(),
e.g.
p1 <- ggplot(df, aes(x,y)) + geom_point()
p1 + theme(aspect.ratio = 1)
p1 + theme(aspect.ratio = (1 + sqrt(5))/ 2) # golden ratio portrait
p1 + theme(aspect.ratio = 2 / (1 + sqrt(5))) # golden ratio landscape
This is, of course, data-agnostic. I think the take-home message is that if you want the scales of your data taken into account, relative to each other, use coord_fixed. If you want to change the aspect ratio of the plotting area but still fit the data, use theme(aspect.ratio). If you want to change the aspect ratio of a saved file, use the height and width arguments of your saving function.

geom_text() size definitions in ggplot2

I'm trying to vary the size of a geom_text() layer in a ggplot so that the labels are always narrower than a given range. The ranges are defined in the data, but what I don't know is how to scale the label to be narrower than that, without a ton of trial and error.
What I hope is that I can construct a function of label size and nchar(label) (realizing character width varies a bit) that would return a width that I could compare to the shape width, and scale down until no longer necessary.
Are the ggplot label sizes defined as a number of pixels, percentage of the plot height, or something else like that?
would this be a helpful place to start? (if not please feel free to delete my post). You add your ranges to ranges = rnorm(foo, 5, 1).
library(ggplot2)
library(directlabels)
set.seed(67)
foo <- 8
df <- data.frame(x = rnorm(foo, 1, .5), y=rnorm(foo, 1, .5), ranges = rnorm(foo, 5, 1), let=letters[1:foo])
p <- ggplot(df, aes(x, y, color=let)) + geom_point() + scale_colour_brewer(palette=5)
direct.label(p,
list("top.points", rot=0, cex=df[,3],
fontface="bold", fontfamily="serif", alpha=0.8))

How to control ggplot's plotting area proportions instead of fitting them to devices in R?

By default, each plot in ggplot fits its device.
That's not always desirable. For instance, one may need to make tiles in geom_tile to be squares. Once you change the device or change the number of elements on x/y-axis, the tiles are no longer squares.
Is it possible to set hard proportions or size for a plot and fit the plot in its device's window (or make the device width and height proportional to those of the plot)?
You can specify the aspect ratio of your plots using coord_fixed().
> library(ggplot2)
> df <- data.frame(
+ x = runif(100, 0, 5),
+ y = runif(100, 0, 5))
If we just go ahead and plot these data then we get a plot which conforms to the dimensions of the output device.
> ggplot(df, aes(x=x, y=y)) + geom_point()
If, however, we use coord_fixed() then we get a plot with fixed aspect ratio (which, by default has x- and y-axes of same length). The size of the plot will be determined by the shortest dimension of the output device.
> ggplot(df, aes(x=x, y=y)) + geom_point() + coord_fixed()
Finally, we can adjust the fixed aspect ratio by specifying an argument to coord_fixed(), where the argument is the ratio of the length of the y-axis to the length of the x-axis. So, to get a plot that is twice as tall as it is wide, we would use:
> ggplot(df, aes(x=x, y=y)) + geom_point() + coord_fixed(2)
A cleaner way is to use the theme(aspect.ratio) argument e.g.
library(ggplot2)
d <- data.frame(x=rnorm(100),y=rnorm(100)*1000)
ggplot(d,aes(x,y))+
geom_point() +
theme(aspect.ratio=1/10) #Long and skinny
coord_fixed() sets the ratio of x/y coordinates, which isn't always the same thing (e.g. in this case, where the units of x and y are very different.
Here's an easy device to treat your plot with respect,
library(ggplot2)
p = qplot(1:10, (1:10)^3)
g = ggplotGrob(p)
g$respect = TRUE
library(grid)
grid.draw(g)

Resources