I would like to add a strip plot to the bottom of a geom_density plot... I could do something like :
ggplot(data = iris, aes(x = Sepal.Length)) +
geom_density(fill = "#2D708EFF", alpha = .2) +
geom_point(aes(y = 0), alpha = .4, shape = 73, size = 6)
But is there a more elegant way of doing this with ggplot2? My keywords might be off, but so far I haven't been able to find another ggplot2 solution.
You must be looking for geom_rug()
library(ggplot2)
ggplot(data = iris, aes(x = Sepal.Length)) +
geom_density(fill = "#2D708EFF", alpha = .2) +
# geom_point(aes(y = 0), alpha = .4, shape = 73, size = 6) +
geom_rug()
A rug plot is a compact visualisation designed to supplement a 2d display with the two 1d marginal distributions. Rug plots display individual cases so are best used with smaller datasets.
Related
Does anyone know how to make the the value of the grid line appear on the grid line in ggplot2?
I have a very large plot that I want to display the grid line value on intermittently throughout the plot, so when you are zoomed in you can easily tell what the value is. The only way I can currently think to do that is to add the labels with another data frame or something with the label and the x, y position. I was wondering if there was a more efficient way or an actual built in mechanism to do this.
Thanks!
There is no option built-in to do this specifically, but it is pretty straightforward using expand.grid to create the grid points and labels, then simply draw the result on with geom_text:
library(ggplot2)
gridlines <- expand.grid(Petal.Width = seq(0, 2, 0.5),
Sepal.Length = seq(4, 8),
Species = "setosa")
ggplot(iris, aes(Sepal.Length, Petal.Width, color = Species)) +
geom_point() +
geom_text(data = gridlines, color = "gray50", aes(label = Sepal.Length),
angle = 90, vjust = -0.5, nudge_y = 0.25) +
geom_text(data = gridlines, color = "gray50", aes(label = Petal.Width),
vjust = -0.5, nudge_x = 0.5) +
theme_bw(base_size = 20) +
theme(panel.grid.minor = element_blank())
Created on 2022-09-05 with reprex v2.0.2
A very similar question to the one asked here. However, in that situation the fill parameter for the two plots are different. For my situation the fill parameter is the same for both plots, but I want different color schemes.
I would like to manually change the color in the boxplots and the scatter plots (for example making the boxes white and the points colored).
Example:
require(dplyr)
require(ggplot2)
n<-4*3*10
myvalues<- rexp((n))
days <- ntile(rexp(n),4)
doses <- ntile(rexp(n), 3)
test <- data.frame(values =myvalues,
day = factor(days, levels = unique(days)),
dose = factor(doses, levels = unique(doses)))
p<- ggplot(data = test, aes(x = day, y = values)) +
geom_boxplot( aes(fill = dose))+
geom_point( aes(fill = dose), alpha = 0.4,
position = position_jitterdodge())
produces a plot like this:
Using 'scale_fill_manual()' overwrites the aesthetic on both the boxplot and the scatterplot.
I have found a hack by adding 'colour' to geom_point and then when I use scale_fill_manual() the scatter point colors are not changed:
p<- ggplot(data = test, aes(x = day, y = values)) +
geom_boxplot(aes(fill = dose), outlier.shape = NA)+
geom_point(aes(fill = dose, colour = factor(test$dose)),
position = position_jitterdodge(jitter.width = 0.1))+
scale_fill_manual(values = c('white', 'white', 'white'))
Are there more efficient ways of getting the same result?
You can use group to set the different boxplots. No need to set the fill and then overwrite it:
ggplot(data = test, aes(x = day, y = values)) +
geom_boxplot(aes(group = interaction(day, dose)), outlier.shape = NA)+
geom_point(aes(fill = dose, colour = dose),
position = position_jitterdodge(jitter.width = 0.1))
And you should never use data$column inside aes - just use the bare column. Using data$column will work in simple cases, but will break whenever there are stat layers or facets.
I'm trying to make a custom plot of some vegan rda results in ggplot2. I'm essentially modifying directions as seen in Plotting RDA (vegan) in ggplot, so that I am using shape and color labels to convey some information about the sample points.
I set up a pca analysis with vegan as follows
library(vegan)
library(dplyr)
library(tibble)
library(ggplot2)
cbPalette <- c("#000000", "#E69F00", "#56B4E9", "#009E73", "#0072B2", "#D55E00", "#CC79A7", "#F0E442")
data(dune)
data(dune.env)
dune.pca <- rda(dune)
uscores <- data.frame(dune.pca$CA$u)
uscores1 <- inner_join(rownames_to_column(dune.env), rownames_to_column(data.frame(uscores)), type = "right", by = "rowname")
vscores <- data.frame(dune.pca$CA$v)
I can make a simple biplot
biplot(dune.pca)
Now, lets say I want to know more about the management conditions to which these different samples were subject. I'll color and shape code them and plot with ggplot.
p1 <- ggplot(uscores1, aes(x = PC1, y = PC2, col = Management,
shape = Management)) +
geom_point() +
scale_color_manual(values=cbPalette) +
scale_fill_manual(values=cbPalette) +
scale_shape_manual(values = c(21:25)) +
theme_bw() +
theme(strip.text.y = element_text(angle = 0))
p1
Next, I'd really like to add some biplot arrows that show us the axes corresponding to species abundance. I can use ggplot to plot just those arrows as follows:
p2 <- ggplot() + geom_text(data = vscores, aes(x = PC1, y = PC2, label = rownames(vscores)), col = 'red') +
geom_segment(data = vscores, aes(x = 0, y = 0, xend = PC1, yend = PC2), arrow=arrow(length=unit(0.2,"cm")),
alpha = 0.75, color = 'darkred')
p2
What I'd really like to do though, is get those arrows and points on the same plot. Currently this is the code that I am trying to use:
p3 <- p1 + geom_text(data = vscores, aes(x = PC1, y = PC2, label = rownames(vscores)), col = 'red') +
geom_segment(data = vscores, aes(x = 0, y = 0, xend = PC1, yend = PC2), arrow=arrow(length=unit(0.2,"cm")),
alpha = 0.75, color = 'darkred')
p3
To my annoyance, this yields only a blank plot (empty window, no error messages). Clearly I am missing something or scaling something incorrectly. Any suggestions about how I can best superimpose the last two plots?
Check ggvegan package from github. It is still in 0.0 versions, and not actively developed at the moment, but if you say
library(ggvegan)
autoplot(dune.pca) # your result object
You get this graph which you can customize in the usual ggplot2 way with various aesthetics.
Try:
library(cowplot) #not needed I just had it attached while answering the question hence the theme.
library(ggplot2)
ggplot(uscores1) +
geom_point(aes(x = PC1, y = PC2, col = Management,
shape = Management)) +
scale_color_manual(values=cbPalette) +
scale_fill_manual(values=cbPalette) +
scale_shape_manual(values = c(21:25)) +
geom_text(data = vscores, aes(x = PC1, y = PC2, label = rownames(vscores)), col = 'red') +
geom_segment(data = vscores, aes(x = 0, y = 0, xend = PC1, yend = PC2), arrow=arrow(length=unit(0.2,"cm")),
alpha = 0.75, color = 'darkred')+
theme_bw() +
theme(strip.text.y = element_text(angle = 0))
The p1 plot was passing col and shape variable Management to geom_text/geom_segment since they were not defined there but there is no Management column in data = vscores. At least I think so based on the error:
`Error in eval(expr, envir, enclos) : object 'Management' not found`
You should also take a look at ggordiplots on GitHub (https://github.com/jfq3/ggordiplots). It includes the function gg_env__fit which fits environmental vectors to an ordination plot. All of the functions inthe package silently return data frames that you may use to modify the plots anyway you wish. The package includes a vignette on modifying the plots. You can read the vignettes without having to install the package by going to john-quensen.com and looking at the GitHub page.
I'm trying to create a scatterplot where the points are jittered (geom_jitter), but I also want to create a black outline around each point. Currently I'm doing it by adding 2 geom_jitters, one for the fill and one for the outline:
beta <- paste("beta == ", "0.15")
ggplot(aes(x=xVar, y = yVar), data = data) +
geom_jitter(size=3, alpha=0.6, colour=my.cols[2]) +
theme_bw() +
geom_abline(intercept = 0.0, slope = 0.145950, size=1) +
geom_vline(xintercept = 0, linetype = "dashed") +
annotate("text", x = 2.5, y = 0.2, label=beta, parse=TRUE, size=5)+
xlim(-1.5,4) +
ylim(-2,2)+
geom_jitter(shape = 1,size = 3,colour = "black")
However, that results in something like this:
Because jitter randomly offsets the data, the 2 geom_jitters are not in line with each other. How do I ensure the outlines are in the same place as the fill points?
I've see threads about this (e.g. Is it possible to jitter two ggplot geoms in the same way?), but they're pretty old and not sure if anything new has been added to ggplot that would solve this issue
The code above works if, instead of using geom_jitter, I use the regular geom_point, but I have too many overlapping points for that to be useful
EDIT:
The solution in the posted answer works. However, it doesn't quite cooperate for some of my other graphs where I'm binning by some other variable and using that to plot different colours:
ggplot(aes(x=xVar, y = yVar, color=group), data = data) +
geom_jitter(size=3, alpha=0.6, shape=21, fill="skyblue") +
theme_bw() +
geom_vline(xintercept = 0, linetype = "dashed") +
scale_colour_brewer(name = "Title", direction = -1, palette = "Set1") +
xlim(-1.5,4) +
ylim(-2,2)
My group variable has 3 levels, and I want to colour each group level by a different colour in the brewer Set1 palette. The current solution just colours everything skyblue. What should I fill by to ensure I'm using the correct colour palette?
You don't actually have to use two layers; you can just use the fill aesthetic of a plotting character with a hole in it:
# some random data
set.seed(47)
df <- data.frame(x = rnorm(100), y = runif(100))
ggplot(aes(x = x, y = y), data = df) + geom_jitter(shape = 21, fill = 'skyblue')
The colour, size, and stroke aesthetics let you customize the exact look.
Edit:
For grouped data, set the fill aesthetic to the grouping variable, and use scale_fill_* functions to set color scales:
# more random data
set.seed(47)
df <- data.frame(x = runif(100), y = rnorm(100), group = sample(letters[1:3], 100, replace = TRUE))
ggplot(aes(x=x, y = y, fill=group), data = df) +
geom_jitter(size=3, alpha=0.6, shape=21) +
theme_bw() +
geom_vline(xintercept = 0, linetype = "dashed") +
scale_fill_brewer(name = "Title", direction = -1, palette = "Set1")
I'm using the code below to generate a simple chart.
# Data import -------------------------------------------------------------
data(mtcars)
mtcars$model <- rownames(mtcars)
# Graph: Income Broadband -------------------------------------------------
# Lib.
require(ggplot2); require(directlabels)
# Graph definition
ggplot(data = mtcars, aes(x = mpg, y = disp)) +
geom_point(shape = 1, colour = "black", size = 3, fill = "black") +
geom_smooth(method = lm, se = TRUE, fullrange = TRUE) +
geom_dl(aes(label = model), list("smart.grid", cex = 0.5, hjust = -.5)) +
xlab("MPG") +
ylab("DISP") +
theme_bw()
As illustrated below, the labels on the chart are placed far away from the points. I would like to amend this and place the point labels closer to the points on the graph. Naturally, for the sake of readability I would like for the labels not overlap. In addition, I would like for the solution to be easy to reproduce as I will have to apply across a number of charts. mlabvpos in Stata, as discussed here, provides some of those functionalities. I'm looking for a similar solution in R.
Edit
Following the comments, it appears the problem is not associated with the hjust settings. For instance, for the code:
# Graph definition
ggplot(data = mtcars, aes(x = mpg, y = disp)) +
geom_point(shape = 1, colour = "black", size = 3, fill = "black") +
geom_smooth(method = lm, se = TRUE, fullrange = TRUE) +
geom_dl(aes(label = model), list("smart.grid", cex = 0.5, hjust = -.001)) +
xlab("MPG") +
ylab("DISP") +
theme_bw()
The labels are still misplaced:
On the same lines, running the code with no hjust settings does not place the labels in a more sensible manner: