library(knitr) options(width = 72)
First, let's load the required packages.
library(particlesizeR) library(mixtools) library(ggplot2)
Now, let's generate a two Gaussian mixture. Because we consider this a particle size distribution, we need to require the values to be positive.
samples <- gen_two_gaussian_mixture(10000, 0.5, 3.0, 1.0, 12.0, 2.0) samples <- samples[samples > 0]
Let's now construct a histogram object. This will give us access to arrays of midpoints and density values.
library(ggplot2) df <- data.frame(samples=samples) plt <- ggplot(df, aes(x=samples)) + geom_histogram(bins=250) print(plt)
Let's look at what is in a ggplot2 histogram, starting at the beginning:
pg <- ggplot_build(plt) head(pg$data[[1]])
Note that we have access to a vector of midpoints (x
) as well as a vector
of lower boundaries (xmin
) and a vector of upper boundaries (xmax
) as
well as the density
and the ncount
.
Next, look at the end of the data...
tail(pg$data[[1]])
Eventually, we want to plot the results. We will build a plot using the newer
ggplot2
package. We will also generate a series of x (diameter) values to
model.
First, we will generate the data
truth <- gen_two_gaussian_dist(0.5, 3.0, 1.0, 12.0, 2.0, 0, 20, 0.1) verbose = FALSE if (verbose == TRUE){ print(c(min(truth), max(truth))) print(max(truth$dist)) print(max(pg$data[[1]]$density)) print(head(truth)) }
pt_line_size <- 1 df_work <- data.frame(diam=pg$data[[1]]$x, density=pg$data[[1]]$density) plt <- ggplot(df_work, aes(diam,density)) + geom_point(size=pt_line_size, colour='darkblue' ) + geom_line(data=truth, aes(x,dist), colour='darkred', size=pt_line_size) + ylab("density") + xlab("diameter [nm]") + ggtitle("Diameter distribution of two Gaussian distributions") + theme(axis.text=element_text(size=12), axis.title=element_text(size=14), plot.title = element_text(hjust = 0.5)) + # center the title NULL print(plt)
We want to compute the mixture model. We will make a guess at the parameters from the histogram.
out <- normalmixEM(samples, lambda=0.5, mu=c( 2, 9.), sigma=c(.8, 2.))
We can now compute the fitted values:
x <- seq(from=0, to=20, by=0.1) fit <- out$lambda[1]*dnorm(x, out$mu[1], out$sigma[1]) + out$lambda[2]*dnorm(x, out$mu[2],out$sigma[2]) df_fit <- data.frame(ecd=x, fit=fit)
And make a final plot.
``````r pt_line_size <- 1 final_plt <- ggplot() + geom_point(data=df_work, aes(diam,density), colour="darkblue", size=pt_line_size) + geom_line(data=df_fit, aes(ecd, fit), colour="darkred", size=pt_line_size) + xlab("size [nm]") + ylab("density") + scale_x_continuous(breaks = seq(from = 0, to = 20, by = 1), limits = c(0, 20)) + scale_y_continuous(breaks = seq(from = 0, to = 0.25, by = 0.05), limits = c(0, 0.25)) + ggtitle("Diameter distribution from two Gaussian distributions") + labs(caption = 'jrminter@gmail.com / @jrminter') + theme(axis.text=element_text(size=12), axis.title=element_text(size=12), plot.title=element_text(hjust = 0.5)) + # center the title NULL print(final_plt)
```
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.